From 571088f49271382a3590eb86df6cca8b89ca91df Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sat, 26 Sep 2026 17:15:04 -0700 Subject: [PATCH 01/67] agent: run the final-message check on a capped answer When a turn hits the tool-call cap, finalAnswer returned the model's tools-disabled reply without ev.CheckFinal, so a definition with an output contract could end a capped turn "succeeded" with no output: the daemon's correction round is what usually pushes a reviewer to the cap, and the answer it forced skipped the very check that asked for it. The capped answer now goes through the same check the loop runs on a no-tools reply, with the one correction round the check may ask for. A second miss fails the turn, as it does in the loop. Co-Authored-By: Claude Fable 5.1 --- internal/agent/agent.go | 26 ++++++- internal/agent/final_answer_test.go | 117 ++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 internal/agent/final_answer_test.go diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 30e63d8a0..5e864fdcb 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -1235,8 +1235,32 @@ func (a *Agent) ManualCompact(ctx context.Context, ev Events) error { // finalAnswer makes one last completion with tools disabled, so a run that hit // the tool-turn cap still returns the model's best answer instead of an error. -// A system nudge tells the model to stop calling tools and answer now. +// The capped answer goes through the same final-message check the loop runs +// on a no-tools reply: a definition's output contract is a property of the +// turn, not of how it ended. One correction round is allowed, as in the loop; +// a second miss fails the turn. func (a *Agent) finalAnswer(ctx context.Context, ev Events) (string, error) { + text, err := a.cappedAnswer(ctx, ev) + if err != nil || ev.CheckFinal == nil { + return text, err + } + retry, err := ev.CheckFinal(text) + if err != nil || !retry { + return text, err + } + if text, err = a.cappedAnswer(ctx, ev); err != nil { + return text, err + } + if _, err := ev.CheckFinal(text); err != nil { + return "", err + } + return text, nil +} + +// cappedAnswer is one tools-disabled completion. A system nudge tells the +// model to stop calling tools and answer now; the turn's ephemeral notices +// (an output-contract correction among them) ride along as usual. +func (a *Agent) cappedAnswer(ctx context.Context, ev Events) (string, error) { msgs := append(slices.Clone(withEphemeralSystem(a.Messages, ev.ephemeral())), llm.Message{Role: "system", Content: "You have reached the tool-call limit. Do NOT request any more tools. Give your final answer now using only what you have already gathered."}) client := *a.Client diff --git a/internal/agent/final_answer_test.go b/internal/agent/final_answer_test.go new file mode 100644 index 000000000..12f79a5e2 --- /dev/null +++ b/internal/agent/final_answer_test.go @@ -0,0 +1,117 @@ +package agent + +import ( + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/tools" +) + +// A turn that hits the cap ends with a tools-disabled answer. That answer must +// pass the same final-message check a no-tools reply does, with the one +// correction round the check may ask for. +func TestFinalAnswerRunsCheckFinalWithOneCorrection(t *testing.T) { + t.Parallel() + var finals []string + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var request llm.Request + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + http.Error(w, "bad request", http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "text/event-stream") + switch { + case len(request.Tools) > 0: + fmt.Fprint(w, `data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"c1","type":"function","function":{"name":"echo","arguments":"{\"s\":\"work\"}"}}]}}]}`+"\n\n") + default: + // The correction notice rides as an ephemeral system message + // ahead of the tools-disabled nudge. + var system []string + for _, message := range request.Messages { + if message.Role == "system" { + system = append(system, message.Content) + } + } + joined := strings.Join(system, "\n") + finals = append(finals, joined) + answer := "not json" + if strings.Contains(joined, "correct") { + answer = `{"ok":true}` + } + fmt.Fprintf(w, `data: {"choices":[{"delta":{"content":%q},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}`+"\n\n", answer) + } + fmt.Fprint(w, "data: [DONE]\n\n") + })) + defer server.Close() + ag := NewRuntime(llm.New(server.URL, "key"), "model", 1024, "system", tools.NewServices()) + defer ag.Services.Close() + ag.Tools = []tools.Tool{echoTool()} + ag.MaxTurns = 1 + var notice string + checks := 0 + ev := Events{ + EphemeralNotices: func() string { return notice }, + CheckFinal: func(text string) (bool, error) { + checks++ + if text == `{"ok":true}` { + return false, nil + } + if checks > 1 { + return false, fmt.Errorf("output_invalid: %q", text) + } + notice = "please correct: reply with one JSON value" + return true, nil + }, + } + final, err := ag.Turn(t.Context(), "go", ev) + if err != nil || final != `{"ok":true}` { + t.Fatalf("capped turn = %q, %v", final, err) + } + if checks != 2 || len(finals) != 2 { + t.Fatalf("checks=%d final calls=%d", checks, len(finals)) + } + if strings.Contains(finals[0], "correct") || !strings.Contains(finals[1], "correct") { + t.Fatalf("correction notice not delivered on the second final call: %q", finals) + } +} + +func TestFinalAnswerFailsTheTurnOnASecondMiss(t *testing.T) { + t.Parallel() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var request llm.Request + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + http.Error(w, "bad request", http.StatusBadRequest) + return + } + w.Header().Set("Content-Type", "text/event-stream") + if len(request.Tools) > 0 { + fmt.Fprint(w, `data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"c1","type":"function","function":{"name":"echo","arguments":"{\"s\":\"work\"}"}}]}}]}`+"\n\n") + } else { + fmt.Fprint(w, `data: {"choices":[{"delta":{"content":"still not json"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}`+"\n\n") + } + fmt.Fprint(w, "data: [DONE]\n\n") + })) + defer server.Close() + ag := NewRuntime(llm.New(server.URL, "key"), "model", 1024, "system", tools.NewServices()) + defer ag.Services.Close() + ag.Tools = []tools.Tool{echoTool()} + ag.MaxTurns = 1 + checks := 0 + _, err := ag.Turn(t.Context(), "go", Events{CheckFinal: func(string) (bool, error) { + checks++ + if checks > 1 { + return false, fmt.Errorf("output_invalid") + } + return true, nil + }}) + if err == nil || !strings.Contains(err.Error(), "output_invalid") || checks != 2 { + t.Fatalf("second miss should fail the turn: err=%v checks=%d", err, checks) + } +} From e9923c5e0278a939ad44b2a0b8b8e03328b2e384 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sat, 26 Sep 2026 19:36:25 -0700 Subject: [PATCH 02/67] agent: errors.New for a constant test error (golangci-lint perfsprint) Co-Authored-By: Claude Fable 5.1 --- internal/agent/final_answer_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/agent/final_answer_test.go b/internal/agent/final_answer_test.go index 12f79a5e2..0504ad172 100644 --- a/internal/agent/final_answer_test.go +++ b/internal/agent/final_answer_test.go @@ -2,6 +2,7 @@ package agent import ( "encoding/json" + "errors" "fmt" "net/http" "net/http/httptest" @@ -107,7 +108,7 @@ func TestFinalAnswerFailsTheTurnOnASecondMiss(t *testing.T) { _, err := ag.Turn(t.Context(), "go", Events{CheckFinal: func(string) (bool, error) { checks++ if checks > 1 { - return false, fmt.Errorf("output_invalid") + return false, errors.New("output_invalid") } return true, nil }}) From 094ecb30b5669e03175d8213d361bf4d89923b91 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sat, 26 Sep 2026 20:37:56 -0700 Subject: [PATCH 03/67] fix(session): carry permission mode over when forking a session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store.Fork's INSERT column list omitted permission_mode, so forks silently reset to the schema default 'prompt' regardless of the source session's consent mode. A Full Access (automatic) session forked into one that prompted again — including file-access authority, which reads permission_mode per root. Add permission_mode to the fork copy so the fork inherits the mode exactly, add TestForkCarriesPermissionMode, and drop TestPermissionModeForkStartsWithDefault, which codified the bug. --- internal/session/fork_test.go | 38 ++++++++++++++++++++++++ internal/session/permission_mode_test.go | 17 ----------- internal/session/session.go | 7 +++-- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/internal/session/fork_test.go b/internal/session/fork_test.go index 95235386e..511d64204 100644 --- a/internal/session/fork_test.go +++ b/internal/session/fork_test.go @@ -139,6 +139,44 @@ func TestForkFullHistory(t *testing.T) { } } +func TestForkCarriesPermissionMode(t *testing.T) { + st, id := seeded(t) + + if err := st.SetPermissionMode(t.Context(), id, PermissionModeAutomatic); err != nil { + t.Fatal(err) + } + forkID, err := st.Fork(id, 2, "full access fork") + if err != nil { + t.Fatal(err) + } + if mode, err := st.PermissionMode(t.Context(), forkID); err != nil || mode != PermissionModeAutomatic { + t.Fatalf("fork permission mode = %q, %v; want %q", mode, err, PermissionModeAutomatic) + } + // the client snapshot for the fork reports the inherited mode + snapshot, err := st.SnapshotRoot(t.Context(), forkID) + if err != nil { + t.Fatal(err) + } + if snapshot.PermissionMode != PermissionModeAutomatic { + t.Fatalf("fork snapshot permission mode = %q, want %q", snapshot.PermissionMode, PermissionModeAutomatic) + } + // the source session keeps its own setting + if mode, err := st.PermissionMode(t.Context(), id); err != nil || mode != PermissionModeAutomatic { + t.Fatalf("source permission mode = %q, %v; want %q", mode, err, PermissionModeAutomatic) + } + // a prompt-mode source forks into a prompt-mode session + if err := st.SetPermissionMode(t.Context(), id, PermissionModePrompt); err != nil { + t.Fatal(err) + } + promptFork, err := st.Fork(id, 2, "prompt fork") + if err != nil { + t.Fatal(err) + } + if mode, err := st.PermissionMode(t.Context(), promptFork); err != nil || mode != PermissionModePrompt { + t.Fatalf("prompt fork permission mode = %q, %v; want %q", mode, err, PermissionModePrompt) + } +} + func TestForkTitle(t *testing.T) { st, id := seeded(t) diff --git a/internal/session/permission_mode_test.go b/internal/session/permission_mode_test.go index 537367f68..c97849723 100644 --- a/internal/session/permission_mode_test.go +++ b/internal/session/permission_mode_test.go @@ -50,20 +50,3 @@ func TestPermissionModeCommitsSnapshotAndEventTogether(t *testing.T) { t.Fatalf("missing root error=%v", err) } } - -func TestPermissionModeForkStartsWithDefault(t *testing.T) { - store, rootID := seeded(t) - if err := store.SetPermissionMode(t.Context(), rootID, PermissionModeAutomatic); err != nil { - t.Fatal(err) - } - forkID, err := store.Fork(rootID, 1, "fork") - if err != nil { - t.Fatal(err) - } - if mode, err := store.PermissionMode(t.Context(), forkID); err != nil || mode != PermissionModePrompt { - t.Fatalf("fork mode=%q error=%v", mode, err) - } - if mode, err := store.PermissionMode(t.Context(), rootID); err != nil || mode != PermissionModeAutomatic { - t.Fatalf("source mode=%q error=%v", mode, err) - } -} diff --git a/internal/session/session.go b/internal/session/session.go index 5a5645aa1..060502942 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -934,7 +934,8 @@ func (s *Store) SetTitleIf(id, current, title string) (bool, error) { // Fork copies a session's stored rows with seq <= uptoSeq (pass len(msgs) // for a full copy — one past the last row) into a new session titled title, -// carrying over cwd/model/provider/goal, and returns the new id. seq equals +// carrying over cwd/model/provider/goal and the permission mode, and returns +// the new id. seq equals // the conversation index (the system prompt is never persisted). The source // session is untouched. The fork also gets a snapshot of active content grants // readable by the source root. It shares immutable references, preserving their @@ -949,8 +950,8 @@ func (s *Store) Fork(srcID string, uptoSeq int, title string) (string, error) { if err != nil { return "", err } - result, err := tx.ExecContext(context.Background(), `INSERT INTO sessions (id,kind,created_at,updated_at,cwd,model,provider,title,goal,forked_from,fork_seq,effort,execution_engine,definition,definition_revision) - SELECT ?,kind,?,?,cwd,model,provider,?,goal,?,?,effort,execution_engine,definition,definition_revision FROM sessions WHERE id=? AND kind='agent'`, + result, err := tx.ExecContext(context.Background(), `INSERT INTO sessions (id,kind,created_at,updated_at,cwd,model,provider,title,goal,forked_from,fork_seq,effort,permission_mode,execution_engine,definition,definition_revision) + SELECT ?,kind,?,?,cwd,model,provider,?,goal,?,?,effort,permission_mode,execution_engine,definition,definition_revision FROM sessions WHERE id=? AND kind='agent'`, newID, now(), now(), title, srcID, uptoSeq, srcID) if err != nil { return "", err From 54fca9c1af25fb85bbf581f05ed5a401bcc5fb2f Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sun, 27 Sep 2026 15:11:00 -0700 Subject: [PATCH 04/67] title generation fixes --- .ai-docs/plans/web-app/WORKFLOW-INVENTORY.md | 3 +- apps/desktop/scripts/onboarding-smoke.mjs | 10 +- .../scripts/session-title-notifications.mjs | 78 +++ cmd/whip/daemon_test.go | 3 + cmd/whip/main_test.go | 23 +- cmd/whip/run_test.go | 41 +- docs/concurrency.md | 17 + docs/features.md | 39 ++ docs/frontend.md | 28 + docs/protocol-v2.md | 20 + internal/daemon/agent_session.go | 83 ++- internal/daemon/child_commit_test.go | 2 +- internal/daemon/client_control.go | 23 +- .../daemon/client_control_archive_test.go | 174 ++++++ internal/daemon/control.go | 112 ++++ internal/daemon/daemon.go | 49 +- internal/daemon/definition_test.go | 7 +- internal/daemon/input_lifecycle_test.go | 22 +- internal/daemon/metadata_routing_test.go | 161 +++++ .../model_accounting_acceptance_test.go | 11 +- internal/daemon/permission_mode_test.go | 2 +- internal/daemon/prompt_test.go | 1 + internal/daemon/provider_connections_test.go | 2 +- internal/daemon/recursive_runtime_test.go | 8 +- internal/daemon/report_restore_test.go | 2 +- internal/daemon/runtime_parity_test.go | 2 +- internal/daemon/server.go | 29 +- internal/daemon/session.go | 125 +++- internal/daemon/session_test.go | 30 +- internal/daemon/subscription_runtime_test.go | 4 +- internal/daemon/title_lifecycle_test.go | 560 ++++++++++++++++++ internal/daemon/title_notifications.go | 61 ++ internal/daemon/title_notifications_test.go | 531 +++++++++++++++++ internal/daemon/v2_sdk_agents_test.go | 1 + internal/protocol/registry.go | 7 + internal/protocol/registry_test.go | 18 + internal/protocol/runtime_registry.go | 1 - internal/protocol/types.go | 2 + internal/session/command.go | 8 +- internal/session/inbox_queue.go | 1 + internal/session/input_lifecycle_test.go | 10 +- internal/session/metadata_test.go | 9 + internal/session/runtime.go | 25 +- internal/session/session.go | 38 +- internal/session/title.go | 130 +++- internal/session/title_admission_test.go | 340 +++++++++++ internal/session/title_test.go | 4 +- internal/session/transcript_test.go | 11 + internal/tui/client.go | 11 - internal/tui/client_test.go | 10 +- internal/tui/startup_test.go | 6 +- packages/app/src/details/session-controls.tsx | 16 - packages/app/src/runtime.ts | 27 + packages/app/src/session-actions.tsx | 22 +- packages/app/src/session-sidebar.tsx | 5 +- packages/app/src/settings/agents.tsx | 2 +- packages/app/test/inspector.test.tsx | 6 +- packages/app/test/session-actions.test.tsx | 44 +- packages/app/test/session-tab-titles.test.tsx | 112 ++++ .../test/session-title-notifications.test.ts | 137 +++++ packages/app/test/settings-agents.test.tsx | 2 + packages/protocol/generated/index.d.ts | 6 +- packages/protocol/generated/index.js | 9 +- .../protocol/generated/request-validators.js | 431 ++++++++------ .../protocol/generated/response-validators.js | 409 +++++++------ .../schema/SessionTitleChangedParams.json | 15 + packages/protocol/schema/manifest.json | 9 +- packages/sdk/src/client.ts | 7 +- packages/sdk/src/state.ts | 46 +- packages/sdk/test/client.test.ts | 36 ++ packages/sdk/test/state.test.ts | 164 ++++- 71 files changed, 3790 insertions(+), 610 deletions(-) create mode 100644 apps/web/scripts/session-title-notifications.mjs create mode 100644 internal/daemon/metadata_routing_test.go create mode 100644 internal/daemon/title_lifecycle_test.go create mode 100644 internal/daemon/title_notifications.go create mode 100644 internal/daemon/title_notifications_test.go create mode 100644 internal/session/title_admission_test.go create mode 100644 packages/app/test/session-tab-titles.test.tsx create mode 100644 packages/app/test/session-title-notifications.test.ts create mode 100644 packages/protocol/schema/SessionTitleChangedParams.json diff --git a/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md b/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md index ea7c58dd0..2c71942ca 100644 --- a/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md +++ b/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md @@ -129,7 +129,6 @@ The operation list is checked against the generated manifest by `packages/app/te | `runtime:schedule.create` | Web | Inspector → Goals & schedules: save/run/clear/form goal, create/delete schedules. | | `runtime:schedule.delete` | Web | Inspector → Goals & schedules: save/run/clear/form goal, create/delete schedules. | | `runtime:schedule.list` | Internal | Schedule inspection comes from bounded root snapshot/collection pages. | -| `runtime:session.autotitle` | Web | Inspector context: enable automatic titles. The existing one-way operation has no disable or readback contract, so the UI does not invent a toggle. | | `runtime:session.create` | Web | Welcome/sidebar/session menu and conversation history controls. Fork/rewind/clear use displayed history revision; rewind confirms possible file restoration. | | `runtime:session.delete` | Web | Welcome/sidebar/session menu and conversation history controls. Fork/rewind/clear use displayed history revision; rewind confirms possible file restoration. | | `runtime:session.effort` | Web | Inspector → Context & model → Model & reasoning, with idle checks and explicit advanced runtime overrides. | @@ -170,4 +169,4 @@ The operation list is checked against the generated manifest by `packages/app/te - Host, mailbox, directory/theme discovery, attachment grants/limits/integrity, clear revision checks, and generated contract behavior have Go tests; affected race suites run separately. - Built SDK acceptance exercises Unix/WebSocket equivalents, multimodal snapshot/history/SessionView, changed payloads and grants, clear revision invalidation, and queued attachment crash recovery. - `packages/app/test/inspector.test.tsx` covers actual agent control payloads, stale-target avoidance, goal/schedule commands, saved-rule deletion, bounded mailbox paging/revision recovery, and ephemeral MCP secret handling. It is a component workflow test using a fake SDK service, not a real provider/OS integration test. -- Application lifetime/recovery, conversation/request workflows, theme accessibility, production packaging, and browser/mobile tests are tracked by their own suites and the main plan. Provider validation/rotation and the one-way automatic-title enable action have focused component tests, including secret disposal on host switch. Arbitrary manual execution, terminal/editor/review work, and runtime process management remain deferred; this inventory does not assert full TUI parity. +- Application lifetime/recovery, conversation/request workflows, theme accessibility, production packaging, and browser/mobile tests are tracked by their own suites and the main plan. Provider validation/rotation has focused component tests, including secret disposal on host switch. Session titles are automatic by definition policy; there is no per-session enable action. Arbitrary manual execution, terminal/editor/review work, and runtime process management remain deferred; this inventory does not assert full TUI parity. diff --git a/apps/desktop/scripts/onboarding-smoke.mjs b/apps/desktop/scripts/onboarding-smoke.mjs index 6a0e05599..50a9e7faa 100644 --- a/apps/desktop/scripts/onboarding-smoke.mjs +++ b/apps/desktop/scripts/onboarding-smoke.mjs @@ -69,7 +69,7 @@ async function firstMessageScenario() { const body = JSON.parse(Buffer.concat(chunks).toString('utf8')); assert.equal(body.model, model, 'Title, compaction, and turns must stay on the selected OpenRouter model'); if (!body.stream) { - const naming = body.messages[0].content.startsWith('Name this session.'); + const naming = body.messages[0].content.startsWith('Name this session based on'); requests.push({ kind: naming ? 'title' : 'compaction', model: body.model }); response.writeHead(200, { 'Content-Type': 'application/json' }); response.end(JSON.stringify({ choices: [{ message: { role: 'assistant', content: naming ? title : 'The user asked to calculate 6 * 7. The Starlark tool returned 42.' }, finish_reason: 'stop' }], @@ -170,9 +170,9 @@ async function firstMessageScenario() { const rootId = new URL(page.url()).pathname.split('/s/')[1]; assert(rootId); const root = client.session(rootId); - // Naming is opt-in in the web app. Exercise its existing command while - // the test holds the stream, before the completed exchange triggers it. - assert.equal((await root.command('session.autotitle', {}).result({ signal: AbortSignal.timeout(5000) })).status, 'succeeded'); + // Naming starts with the first message, independently of this held turn. + await expect.poll(() => requests.filter(entry => entry.kind === 'title').length, { timeout: 5000 }).toBe(1); + await expect.poll(async () => (await root.snapshot()).meta.title).toBe(title); await capture(page, 'desktop-first-message-streaming'); releaseAnswer(); await expect(page.getByText(answer, { exact: true }).last()).toBeVisible({ timeout: 15_000 }); @@ -221,7 +221,7 @@ async function firstMessageScenario() { draftedBeforeAuthentication: true, draftPreservedThroughAuthentication: true, maskedKeySavedOnHost: true, defaultPairConfirmedInUI: true, nativeFolderSelected: true, firstMessageCreatedOneSession: true, streamedBeforeCompletion: true, rlmExecRoundTrip: true, titleAndCompactionUseSelectedModel: true, - auxiliaryOperations: 'Title opt-in and manual compaction use existing SDK commands; the first prompt is submitted from the renderer UI.', + auxiliaryOperations: 'Automatic naming starts from the first renderer-submitted message; manual compaction uses the existing SDK command.', reloadPreservesDraft: true, daemonRestartPreservesSessionDefaultsAndPermission: true, requests }; } finally { releaseAnswer?.(); diff --git a/apps/web/scripts/session-title-notifications.mjs b/apps/web/scripts/session-title-notifications.mjs new file mode 100644 index 000000000..b732eda38 --- /dev/null +++ b/apps/web/scripts/session-title-notifications.mjs @@ -0,0 +1,78 @@ +import assert from 'node:assert/strict'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { chromium, firefox, expect } from '@playwright/test'; +import { createWhipClient } from '../../../packages/sdk/dist/index.js'; +import { startFixture } from '../../../packages/sdk/scripts/fixture.mjs'; + +// Real renderer + daemon/WebSocket, with two-second polling lengthened only in +// this fixture so passing cannot be attributed to the fallback sync path. +const output = process.env.WHIP_TITLE_NOTIFICATION_RESULTS ?? '/tmp/whip-title-notifications-browser'; +await mkdir(output, { recursive: true }); +for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(',')) { + const fixture = await startFixture(); + const browser = await ({ chromium, firefox }[engine]).launch(); + const client = createWhipClient({ endpoint: fixture.info.endpoint, clientId: crypto.randomUUID(), clientKind: 'human' }); + const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } }); + const sent = [], received = [], errors = []; + page.on('pageerror', error => errors.push(error.message)); + page.on('websocket', socket => { + socket.on('framesent', ({ payload }) => { try { sent.push(JSON.parse(String(payload))); } catch {} }); + socket.on('framereceived', ({ payload }) => { try { received.push(JSON.parse(String(payload))); } catch {} }); + }); + await page.addInitScript(() => { + const timeout = window.setTimeout.bind(window), interval = window.setInterval.bind(window); + window.setTimeout = (handler, delay, ...args) => timeout(handler, delay === 2000 ? 60000 : delay, ...args); + window.setInterval = (handler, delay, ...args) => interval(handler, delay === 2000 ? 60000 : delay, ...args); + }); + const origin = fixture.info.endpoint.replace(/^ws/, 'http').replace('/api/v3/ws', ''); + const route = id => origin + '/h/' + fixture.info.runtime_id + '/s/' + id; + const row = id => page.locator('[data-sidebar-session="' + id + '"]'); + try { + await client.connect(); + assert(client.getSnapshot().info.negotiated_capabilities.includes('session_title_notifications')); + const active = fixture.info.root_id; + const roots = []; + for (const title of ['Inactive old title', 'Unopened old title']) { + const result = await client.sessions.create({ cwd: fixture.directory, model: 'model', provider: 'provider' }).result(); + assert.equal(result.status, 'succeeded'); + roots.push(result.result.root_id); + assert.equal((await client.session(roots.at(-1)).rename(title).result()).status, 'succeeded'); + } + const [inactive, unopened] = roots; + await page.goto(route(inactive)); + await expect(row(inactive)).toBeVisible({ timeout: 15000 }); + await row(active).getByRole('link').click(); + await expect(page).toHaveURL(route(active)); + await expect(page.getByRole('tab', { name: /Inactive old title/ }).first()).toBeVisible(); + await expect(row(unopened)).toContainText('Unopened old title'); + received.length = 0; + const started = performance.now(); + assert.equal((await client.session(inactive).rename('Inactive new title').result()).status, 'succeeded'); + assert.equal((await client.session(unopened).rename('Unopened new title').result()).status, 'succeeded'); + await expect(page.getByRole('tab', { name: /Inactive new title/ }).first()).toBeVisible({ timeout: 3000 }); + await expect(row(inactive)).toContainText('Inactive new title', { timeout: 3000 }); + await expect(row(unopened)).toContainText('Unopened new title', { timeout: 3000 }); + assert(received.some(frame => frame.method === 'sessions.title.changed' && frame.params.root_id === inactive)); + assert(received.some(frame => frame.method === 'sessions.title.changed' && frame.params.root_id === unopened)); + // The formerly active view may remain leased for 30 seconds; existing root + // events can still refresh it. The never-opened session is the strict proof + // that a host notification needs no root hydration. + assert(!sent.some(frame => ['events.subscribe', 'root.snapshot'].includes(frame.method) && frame.params.root_id === unopened), 'Unopened root was hydrated'); + assert.deepEqual(errors, []); + await page.screenshot({ path: join(output, engine + '.png') }); + await writeFile(join(output, engine + '.json'), JSON.stringify({ + engine, changedWithinMs: performance.now() - started, pollingIntervalInFixtureMs: 60000, + notificationRoots: received.filter(frame => frame.method === 'sessions.title.changed').map(frame => frame.params.root_id), + unopenedRootNeverHydrated: true, inactiveTabUpdated: true, errors, + }, null, 2)); + console.log(engine + ': title notification updates inactive tab and unopened sidebar session'); + } catch (error) { + await writeFile(join(output, engine + "-failure.json"), JSON.stringify({ sent, received, errors }, null, 2)); + throw error; + } finally { + client.close(); + await browser.close(); + await fixture.close(); + } +} diff --git a/cmd/whip/daemon_test.go b/cmd/whip/daemon_test.go index b145822cb..fdc7baa49 100644 --- a/cmd/whip/daemon_test.go +++ b/cmd/whip/daemon_test.go @@ -195,6 +195,9 @@ func TestRunDaemonAlwaysUsesRLMRuntime(t *testing.T) { http.Error(w, err.Error(), http.StatusBadRequest) return } + if respondToTitleRequest(t, w, input) { + return + } requests <- input call := calls.Add(1) w.Header().Set("Content-Type", "text/event-stream") diff --git a/cmd/whip/main_test.go b/cmd/whip/main_test.go index 27c24d891..d7d85cf4a 100644 --- a/cmd/whip/main_test.go +++ b/cmd/whip/main_test.go @@ -166,7 +166,7 @@ func TestMainDispatchesHeadlessCommands(t *testing.T) { func TestClientEntryPathsSendAssembledPromptToProvider(t *testing.T) { for _, kind := range []string{"headless", "acp", "tui"} { t.Run(kind, func(t *testing.T) { - requests, workingDirectory := promptRequestFixture(t) + requests, titles, workingDirectory := promptRequestFixture(t) standing := filepath.Join(os.Getenv("WHIPCODE_HOME"), "me.md") writePromptRequestFile(t, standing, "# COMMENT_MUST_NOT_REACH_MODEL\nSTANDING_BEFORE_EDIT") writePromptRequestFile(t, filepath.Join(workingDirectory, "CLAUDE.md"), "CLAUDE_REQUEST_MARKER") @@ -180,6 +180,12 @@ func TestClientEntryPathsSendAssembledPromptToProvider(t *testing.T) { writePromptRequestFile(t, standing, standingMarker) } submit("verify prompt environment") + if turn == 0 { + title := readPromptRequest(t, titles) + if len(title.Messages) != 2 || title.Messages[1].Content != "verify prompt environment" { + t.Fatalf("title request must contain only the accepted user prompt: %+v", title.Messages) + } + } request := readPromptRequest(t, requests) if len(request.Messages) < 2 || request.Messages[0].Role != "system" { t.Fatalf("request has no system prompt: %#v", request.Messages) @@ -202,7 +208,7 @@ func TestClientEntryPathsSendAssembledPromptToProvider(t *testing.T) { } func TestHeadlessSystemOverrideReachesProviderExactly(t *testing.T) { - requests, workingDirectory := promptRequestFixture(t) + requests, _, workingDirectory := promptRequestFixture(t) writePromptRequestFile(t, filepath.Join(os.Getenv("WHIPCODE_HOME"), "me.md"), "NORMAL_STANDING_RULE") writePromptRequestFile(t, filepath.Join(workingDirectory, "AGENTS.md"), "NORMAL_PROJECT_RULE") const override = "Exact user system override.\nKeep this byte-for-byte." @@ -216,13 +222,15 @@ func TestHeadlessSystemOverrideReachesProviderExactly(t *testing.T) { } func TestHeadlessRejectsIncompleteInstructionsBeforeProvider(t *testing.T) { - requests, workingDirectory := promptRequestFixture(t) + requests, _, workingDirectory := promptRequestFixture(t) if err := os.Mkdir(filepath.Join(workingDirectory, "AGENTS.md"), 0o700); err != nil { t.Fatal(err) } if _, err := runCapture(t, "", "-quiet", "hello"); err == nil || !strings.Contains(err.Error(), "expected a regular file") { t.Fatalf("invalid applicable rules must fail the run explicitly: %v", err) } + // Prompt-only naming may run after admission; the conversation must not run + // with incomplete instructions. select { case request := <-requests: t.Fatalf("provider ran with incomplete instructions: %#v", request.Messages) @@ -230,7 +238,7 @@ func TestHeadlessRejectsIncompleteInstructionsBeforeProvider(t *testing.T) { } } -func promptRequestFixture(t *testing.T) (<-chan llm.Request, string) { +func promptRequestFixture(t *testing.T) (<-chan llm.Request, <-chan llm.Request, string) { t.Helper() t.Setenv("HOME", t.TempDir()) home := t.TempDir() @@ -241,6 +249,7 @@ func promptRequestFixture(t *testing.T) (<-chan llm.Request, string) { t.Fatal(err) } requests := make(chan llm.Request, 8) + titles := make(chan llm.Request, 8) server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") != "Bearer fixture-file-key" { t.Error("entrypoint did not send its configured file key") @@ -252,6 +261,10 @@ func promptRequestFixture(t *testing.T) (<-chan llm.Request, string) { http.Error(w, err.Error(), http.StatusBadRequest) return } + if respondToTitleRequest(t, w, request) { + titles <- request + return + } select { case requests <- request: case <-r.Context().Done(): @@ -271,7 +284,7 @@ func promptRequestFixture(t *testing.T) (<-chan llm.Request, string) { "models":{"test":{"providers":["testprov"],"context":65536,"maxOut":128}} }`, keyPath, server.URL)) useTestDaemon(t) - return requests, workingDirectory + return requests, titles, workingDirectory } func writePromptRequestFile(t *testing.T, path, text string) { diff --git a/cmd/whip/run_test.go b/cmd/whip/run_test.go index 07ee19c3e..a510dd7c5 100644 --- a/cmd/whip/run_test.go +++ b/cmd/whip/run_test.go @@ -19,13 +19,33 @@ import ( "github.com/context-labs/whip/internal/session" ) -// runFixture writes a config pointing the default model at an SSE test -// server that replies with reply (and records each request into reqs). +// respondToTitleRequest handles the daemon's prompt-only naming request without +// adding it to conversation captures or advancing a tool-call fixture. +func respondToTitleRequest(t *testing.T, w http.ResponseWriter, request llm.Request) bool { + t.Helper() + if len(request.Messages) == 0 || request.Messages[0].Role != "system" || + !strings.HasPrefix(request.Messages[0].Content, "Name this session based on") { + return false + } + if request.Stream || len(request.Tools) != 0 || len(request.Messages) != 2 || + request.Messages[1].Role != "user" || strings.TrimSpace(request.Messages[1].Content) == "" { + t.Errorf("title request must be nonstreaming and prompt-only: %+v", request) + } + w.Header().Set("Content-Type", "application/json") + fmt.Fprint(w, `{"choices":[{"message":{"role":"assistant","content":"Fixture session title"},"finish_reason":"stop"}]}`) + return true +} + +// runFixture writes a config pointing the default model at a test server that +// replies with reply and records only conversation requests into reqs. func runFixture(t *testing.T, reply string, reqs *[]llm.Request) { t.Helper() srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var req llm.Request json.NewDecoder(r.Body).Decode(&req) + if respondToTitleRequest(t, w, req) { + return + } if reqs != nil { *reqs = append(*reqs, req) } @@ -273,6 +293,9 @@ func TestRunMaxTurns(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var req llm.Request json.NewDecoder(r.Body).Decode(&req) + if respondToTitleRequest(t, w, req) { + return + } w.Header().Set("Content-Type", "text/event-stream") if len(req.Tools) == 0 { fmt.Fprint(w, `data: {"choices":[{"delta":{"content":"final answer"},"finish_reason":"stop"}]}`+"\n\n") @@ -463,6 +486,9 @@ func TestRunJSONToolEvents(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var req llm.Request json.NewDecoder(r.Body).Decode(&req) + if respondToTitleRequest(t, w, req) { + return + } w.Header().Set("Content-Type", "text/event-stream") if len(req.Tools) == 0 { fmt.Fprint(w, `data: {"choices":[{"delta":{"content":"done"},"finish_reason":"stop"}]}`+"\n\n") @@ -517,6 +543,14 @@ func TestRunJSONToolEvents(t *testing.T) { // of the reply text, so downstream tools can show thinking activity live. func TestRunJSONReasoning(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var req llm.Request + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if respondToTitleRequest(t, w, req) { + return + } w.Header().Set("Content-Type", "text/event-stream") fmt.Fprint(w, `data: {"choices":[{"delta":{"reasoning_content":"let me think"}}]}`+"\n\n") fmt.Fprint(w, `data: {"choices":[{"delta":{"content":"answer"},"finish_reason":"stop"}]}`+"\n\n") @@ -667,6 +701,9 @@ func TestRunAutomaticHeadlessHonorsSavedPermission(t *testing.T) { t.Error(err) return } + if respondToTitleRequest(t, w, req) { + return + } w.Header().Set("Content-Type", "text/event-stream") if lastTranscriptRole(req.Messages) == "tool" || len(req.Tools) == 0 { fmt.Fprint(w, `data: {"choices":[{"delta":{"content":"done"},"finish_reason":"stop"}]}`+"\n\n") diff --git a/docs/concurrency.md b/docs/concurrency.md index 9fd545856..bf56d227d 100644 --- a/docs/concurrency.md +++ b/docs/concurrency.md @@ -4,6 +4,23 @@ whip separates durable ordering from independent execution. One root actor serializes state transitions for a session; model calls, kernels, MCP calls, and unrelated roots may run concurrently under explicit limits. +## Session title invalidation + +Committed title writes notify protocol servers through a small daemon-owned +listener registry. Its dedicated mutex protects listener registration/snapshots +only; callbacks run after that mutex and the root-registry/DB locks are released. +Each Server registers once and unregisters on Close. It snapshots eligible +connections under its mutex, releases it, and uses existing bounded outbound +queues. The per-connection writer remains the only socket writer; slow-client +overflow follows the existing disconnect policy. No title notification spawns a +worker or owns a durable replay cursor. + +Only initialized connections that negotiated `session_title_notifications` receive +`sessions.title.changed`. The root ID is an invalidation hint, not a title value +to apply, so dropped or reordered hints are safe. SDK/AppRuntime listeners own +coalesced refreshes and retire on disposal/detach; polling and reconnect reads +remain authoritative recovery paths. See [frontend ownership](frontend.md). + ## Root actors Every client command receives a stable ID and durable ingress sequence before diff --git a/docs/features.md b/docs/features.md index c9922adcd..b8b6db2ea 100644 --- a/docs/features.md +++ b/docs/features.md @@ -614,6 +614,45 @@ verified tools, helpers, a child, images, title/compaction and restart recovery. inspection and management remain in the session inspector. - Process shutdown is root-owned and waits for supervised workers. +## Session naming + +- Session creation remains promptless. The first accepted user message with usable + text supplies a whitespace-normalized, Unicode-bounded deterministic title before + conversation execution. Multipart text follows the same root-input path; + attachment-only messages wait for authored text rather than invoking vision. A + later execution failure does not undo naming of an already accepted message. +- Deterministic titles shorter than 20 Unicode characters are kept without an LLM + call. At 20 characters or more, automatic naming is enabled by default: one + daemon-owned background request uses the compact-model route (or its existing + main-model fallback), using only the user text, with a 20-second timeout. + Definition `surface.auto_title=false` skips this request but retains the + deterministic title. No separate per-session enablement + command or inspector control is required. +- Failure or shutdown retains the deterministic title; there is no retry job or + old-session backfill. Duplicate input does not schedule another attempt. Manual + rename wins over in-flight generation, and fork names are preserved. Title calls + retain normal model-accounting and budget enforcement. +- Persisted title changes bump the existing catalog revision and emit a negotiated + host-level `sessions.title.changed` notification containing only the root ID. + Deterministic titles (including short titles), generated titles, manual renames, + and newly created forks trigger existing catalog/summary reads without opening + the conversation. Active conversations retain the ordered root title event. +- Notifications are best-effort invalidation hints, not another title cache. SDK + catalogs refresh and Desktop/web invalidates that host's tab/sidebar summaries, + search, and attention queries. Existing polling intervals and visibility gates + remain unchanged as backup; older clients/hosts continue polling. Off-page and + disconnected views read current titles when fetched or reconnected. +- Code: `internal/session/{command,title}.go`, + `internal/daemon/{session,agent_session,client_control}.go`. Validation: session + `internal/session/title_admission_test.go`, daemon title lifecycle and metadata + routing tests (`title_lifecycle_test.go`, `metadata_routing_test.go`), title + model-accounting tests, and notification delivery/lifecycle tests in + `internal/daemon/title_notifications_test.go`. Client coverage lives in + `packages/sdk/test/{client,state}.test.ts` and + `packages/app/test/{session-title-notifications,session-tab-titles}.test.ts*`. + `apps/web/scripts/session-title-notifications.mjs` verifies real WebSocket + delivery and unopened-sidebar/inactive-tab updates in Chromium and Firefox. + ## TypeScript client SDK - Desktop/web active-turn messages enter a durable queue above the composer. diff --git a/docs/frontend.md b/docs/frontend.md index 4db5ed07b..3135f1ce9 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -646,6 +646,13 @@ SDK client and `SessionListView` for each attached daemon. Components subscribe using `useSyncExternalStore` through app hooks or `@whip/sdk/react`. Store snapshots remain immutable and referentially stable between changes. +Optimistic intent lives in the SDK view that owns the data, not in component +state: `SessionListView.setOptimisticArchived` hides or restores a row the +moment the user acts, and every later server publish reconciles the overlay +against the fetched catalog (server truth wins, agreeing entries are dropped). +Callers revert by setting the opposite intent; they never filter server state +themselves. + Local is the daemon supplied by the browser launch endpoint, or the managed This Mac runtime in Electron. Its configuration owns the `remote_hosts` registry, shared by browsers using that local daemon: @@ -1178,6 +1185,27 @@ session listing stays with `SessionListView`; filtered search and host attention are separate reads. Do not confuse agent mailbox messages with queued execution inputs in the root inbox. +Session titles are daemon-owned metadata. The first accepted authored text supplies +a deterministic title; eligible titles get one background compact-model request +without waiting for the conversation turn. The existing `session.title.updated` +root event updates an observed conversation. Connections negotiating +`session_title_notifications` also receive `sessions.title.changed` with only a +`root_id` after committed naming, manual renames, and fork creation. This is a +best-effort invalidation hint, not a title value to apply. + +The SDK `SessionListView` owns its notification listener and reuses its coalesced +catalog refresh. Desktop/web owns one additional listener per attached client in +`AppRuntime`, invalidating only that host's existing tab/sidebar summaries, search, +and attention queries. No per-conversation subscription or second title cache is +created. Query results still supply tab title hints; notifications never overwrite +unsent rename drafts. Reconnect replaces listeners; detach and disposal remove them. + +All existing polling intervals, observation/visibility gates, page bounds, and +reconnect/focus recovery stay unchanged. They cover missed notifications and hosts +without this capability. Off-page sessions get current titles when fetched. Search +invalidation includes all cached terms for the host, because a rename can change +result membership, not only visible text. + The SDK owns snapshot/cursor consistency, replay, subscription IDs, duplicate/gap checks, resynchronization, and history revisions. It processes every event in order and batches notifications (normally 16 ms); it does not drop intermediate diff --git a/docs/protocol-v2.md b/docs/protocol-v2.md index f8c042e27..e3a5a004a 100644 --- a/docs/protocol-v2.md +++ b/docs/protocol-v2.md @@ -310,6 +310,26 @@ Disconnecting cancels connection queries and subscriptions, not accepted work. Cancellation targets a specific turn so a delayed cancellation cannot affect a later turn. Uncertain external effects are interrupted rather than replayed. +Session creation does not take a naming prompt. The first accepted authored text +initializes the deterministic title and may start one background compact-model +request, governed by the definition's `surface.auto_title` policy. There is no +`session.autotitle` opt-in command. `session.rename` remains explicit user intent +and supersedes pending generation. Title writes retain the `session.title.updated` +root event and catalog-revision bump. Connections negotiating +`session_title_notifications` receive this best-effort host-level notification +after a committed deterministic/generated title, manual rename, or fork creation: + +```json +{"jsonrpc":"2.0","method":"sessions.title.changed","params":{"root_id":"root-id"}} +``` + +No root subscription is required. The message carries no title value or stream +cursor: clients refetch their existing catalog/summary data. It is sent only after +initialization, has no acknowledgement or replay, and uses existing bounded +outbound queues. A slow/disconnected client cannot roll back a title write. Keep +ordinary polling and reconnect reads as backup; peers without negotiated support +continue polling. See [session naming](features.md#session-naming). + Read operations travel through `query` with `root_id`, `operation` and typed `payload`, and do not create command journal entries. `operation.invoke` handles explicitly ephemeral operations such as terminal input and MCP attachment. diff --git a/internal/daemon/agent_session.go b/internal/daemon/agent_session.go index 1b170f3ad..fd45e908e 100644 --- a/internal/daemon/agent_session.go +++ b/internal/daemon/agent_session.go @@ -452,39 +452,60 @@ func renderMailboxLine(message sessionstore.MailboxMessage, digest sessionstore. func (session *AgentSession) History() []llm.Message { return session.agent.MessagesSnapshot() } -func (session *AgentSession) GenerateTitle(ctx context.Context) (string, llm.Usage, error) { - var userText, assistantText string - for _, message := range session.agent.MessagesSnapshot() { - if userText == "" && message.Role == "user" && message.Authored { - userText = message.TextContent() - } else if userText != "" && message.Role == "assistant" && strings.TrimSpace(message.TextContent()) != "" { - assistantText = message.TextContent() - break - } - } - if userText == "" || assistantText == "" { - return "", llm.Usage{}, errors.New("title requires a completed exchange") - } - client, model := session.agent.CompactClient, session.agent.CompactModel +func (session *AgentSession) GenerateTitle(ctx context.Context, prompt string) (string, llm.Usage, error) { + return session.prepareTitle(prompt)(ctx) +} + +// prepareTitle snapshots the route on the root actor before the request runs. +// Runtime replacement can retire the old loop without changing this request's +// client, accounting route, or usage owner. No conversation history is read. +func (session *AgentSession) prepareTitle(prompt string) func(context.Context) (string, llm.Usage, error) { + owner := session.agent + client, model := owner.CompactClient, owner.CompactModel if client == nil || model == "" { - client, model = session.agent.Client, session.agent.Model - } - output, usage, err := client.Complete(ctx, llm.Request{ - Model: model, MaxTokens: 24, Accounting: session.agent.CompactAccounting("title"), - Messages: []llm.Message{ - {Role: "system", Content: "Name this session. Reply with a plain 3-6 word title: no quotes and no trailing period."}, - {Role: "user", Content: "Request: " + boundedTitleText(userText, 300) + "\nResponse: " + boundedTitleText(assistantText, 200)}, - }, - }) - session.agent.AddUsage(usage) - if err != nil { - return "", usage, err - } - title := strings.Trim(strings.TrimSpace(output), "\"'.") - if title == "" || len(title) > 80 { - return "", usage, errors.New("model returned an invalid title") + client, model = owner.Client, owner.Model + } + accounting := owner.CompactAccounting("title") + var snapshot llm.Client + if client != nil { + snapshot = *client + // One title attempt, including transport failures. Do not change the + // conversation client's retry policy. + snapshot.MaxRetries = 1 + } + prompt = boundedTitleText(prompt, 300) + return func(ctx context.Context) (string, llm.Usage, error) { + if prompt == "" || client == nil || model == "" { + return "", llm.Usage{}, errors.New("title requires user text and a model route") + } + output, usage, err := snapshot.Complete(ctx, llm.Request{ + Model: model, MaxTokens: 24, Accounting: accounting, + Messages: []llm.Message{ + {Role: "system", Content: `Name this session based on the user's message. + +Write a concise, specific topic label, usually 2–6 words. Prefer a short noun +phrase that captures the main subject or intended change. Avoid filler, +conversational phrasing, and generic words like "discussion", "request", or +"assistance" when they add no meaning. + +Use sentence case: capitalize only the first word, proper nouns, and +abbreviations. Preserve the spelling and casing of technical identifiers. + +Return only the title, with no quotes, markdown, or trailing punctuation. +Do not answer the user's message.`}, + {Role: "user", Content: prompt}, + }, + }) + owner.AddUsage(usage) + if err != nil { + return "", usage, err + } + title := strings.Trim(strings.TrimSpace(output), "\"'.") + if title == "" || len([]rune(title)) > 80 || strings.ContainsAny(title, "\r\n") { + return "", usage, errors.New("model returned an invalid title") + } + return title, usage, nil } - return title, usage, nil } func boundedTitleText(value string, limit int) string { diff --git a/internal/daemon/child_commit_test.go b/internal/daemon/child_commit_test.go index 4add2874b..231524593 100644 --- a/internal/daemon/child_commit_test.go +++ b/internal/daemon/child_commit_test.go @@ -168,7 +168,7 @@ func TestChildCommitFailureInterruptsRootWithoutFalseSuccess(t *testing.T) { return Components{}, err } runtimes[meta.ID] = runtime - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index 9230ad498..dc574fa6b 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -130,7 +130,7 @@ type clientGoal struct { func isClientOperation(operation string) bool { switch operation { case "inbox.steer", "inbox.remove", "cancel", "goal.set", "goal.run", "goal.from-context", "schedule.list", "schedule.create", "schedule.delete", "session.fork", "workspace.inspect", "workspace.set", - "session.effort", "session.model", "session.effort.get", "session.model.get", "session.list", "session.open", "session.rename", "session.archive", "session.reload", "session.autotitle", "run.configure", + "session.effort", "session.model", "session.effort.get", "session.model.get", "session.list", "session.open", "session.rename", "session.archive", "session.reload", "run.configure", "history.clear", "history.rewind", "history.compact", "history.compact.log", "history.compact.retry", "compaction.configure", "history.user.list", "session.preview", "agents.list", "agent.transcript", "agent.submit", "agent.turn.cancel", "question.answer", @@ -1007,13 +1007,19 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw } title := strings.TrimSpace(payload.Title) if title == "" { - var err error - title, err = s.store.ForkTitle(s.meta.Title) + source, err := s.store.LoadMeta(s.meta.ID) + if err != nil { + return "", err + } + title, err = s.store.ForkTitle(source.Title) if err != nil { return "", err } } id, err := s.store.Fork(s.meta.ID, cut, title) + if err == nil { + s.notifyTitleChanged(id) + } return id, err case "workspace.inspect": if runner, ok := s.runner.(clientWorkspaceRunner); ok { @@ -1074,9 +1080,6 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw case "session.model.get": return marshalClientOutput(protocol.ModelResult{Model: s.meta.Model, Provider: s.meta.Provider}, nil) - case "session.autotitle": - s.autoTitle = true - return "configured", nil case "session.list": metas, err := s.store.RecentContext(ctx, 50) return marshalClientOutput(metas, err) @@ -1100,9 +1103,11 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if err := s.store.SetTitle(s.meta.ID, title); err != nil { return "", err } - s.meta.Title = title - s.emitSessionUpdate(ctx, "session.title.updated", SessionUpdateEvent{Title: title}) - return title, nil + if s.titleWork != nil { + s.titleWork.cancel() + s.titleWork = nil + } + return title, s.publishTitle(ctx, title) case "session.archive": if err := s.store.SetArchived(ctx, s.meta.ID, payload.Archived); err != nil { return "", err diff --git a/internal/daemon/client_control_archive_test.go b/internal/daemon/client_control_archive_test.go index a9e67ca2c..03033fc08 100644 --- a/internal/daemon/client_control_archive_test.go +++ b/internal/daemon/client_control_archive_test.go @@ -3,6 +3,7 @@ package daemon import ( "context" "encoding/json" + "os" "path/filepath" "reflect" "testing" @@ -100,8 +101,150 @@ func TestClientArchiveIsDurableIdempotentAndDoesNotStopWork(t *testing.T) { } } +func TestControlSessionMetadataCommandWhenRootCannotOpen(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + missing := filepath.Join(t.TempDir(), "gone") + if err := store.SetWorkingDirectory(rootID, missing); err != nil { + t.Fatal(err) + } + owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + // Production runner construction stats the workspace; mirror that here. + if _, err := os.Stat(meta.CWD); err != nil { + return Components{}, err + } + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + if _, err := owner.Open(rootID); err == nil { + t.Fatal("open should fail for a missing workspace") + } + for _, tc := range []struct { + id, operation, payload string + }{ + {"archive-cold", "session.archive", `{"archived":true}`}, + {"rename-cold", "session.rename", `{"title":"Cold rename"}`}, + } { + raw := json.RawMessage(tc.payload) + digest, err := requestDigest("root", rootID, tc.operation, raw) + if err != nil { + t.Fatal(err) + } + record, err := owner.control.SessionMetadataCommand(t.Context(), session.CommandAdmission{ + ClientID: "client", CommandID: tc.id, RequestDigest: digest, + Payload: session.RuntimePayload{Data: raw, MediaType: "application/json", Source: tc.operation}, + }, tc.operation, raw, rootID) + if err != nil || record.Status != "succeeded" { + t.Fatalf("%s cold root %+v %v", tc.operation, record, err) + } + // Idempotent retry replays the durable record without re-executing. + retry, err := owner.control.SessionMetadataCommand(t.Context(), session.CommandAdmission{ + ClientID: "client", CommandID: tc.id, RequestDigest: digest, + Payload: session.RuntimePayload{Data: raw, MediaType: "application/json", Source: tc.operation}, + }, tc.operation, raw, rootID) + if err != nil || retry.Status != "succeeded" || retry.CommandID != tc.id || retry.IngressSeq != record.IngressSeq { + t.Fatalf("%s retry changed record: %+v %+v %v", tc.operation, record, retry, err) + } + } + meta, err := store.SessionMetadata(t.Context(), rootID) + if err != nil || !meta.Archived || meta.Title != "Cold rename" { + t.Fatalf("metadata not persisted: %+v %v", meta, err) + } + events, _, err := store.ReplayEvents(t.Context(), rootID, 0, 100) + if err != nil { + t.Fatal(err) + } + kinds := []string{} + for _, event := range events { + if event.Kind == "session.archived.updated" || event.Kind == "session.title.updated" { + kinds = append(kinds, event.Kind) + } + } + if !reflect.DeepEqual(kinds, []string{"session.archived.updated", "session.title.updated"}) { + t.Fatalf("metadata events = %v", kinds) + } +} + +func TestArchiveAndRenameColdRootWithoutWorkspace(t *testing.T) { + f := newV2Fixture(t, &fakeRunner{}) + // A worktree deleted after the session last ran: opening must not gate + // catalog mutations. + missing := filepath.Join(t.TempDir(), "gone") + if err := f.store.SetWorkingDirectory(f.rootID, missing); err != nil { + t.Fatal(err) + } + client := f.dial("unix", "archive-cold") + archive, err := client.Command(t.Context(), CommandParams{ + Scope: "root", CommandID: "archive-missing", RootID: f.rootID, Operation: "session.archive", + Payload: json.RawMessage(`{"archived":true}`), + }) + if err != nil || archive.Status != "succeeded" { + t.Fatalf("archive cold root %+v %v", archive, err) + } + meta, err := f.store.SessionMetadata(t.Context(), f.rootID) + if err != nil || !meta.Archived { + t.Fatalf("archive not persisted: %+v %v", meta, err) + } + rename, err := client.Command(t.Context(), CommandParams{ + Scope: "root", CommandID: "rename-missing", RootID: f.rootID, Operation: "session.rename", + Payload: json.RawMessage(`{"title":"Renamed without workspace"}`), + }) + if err != nil || rename.Status != "succeeded" { + t.Fatalf("rename cold root %+v %v", rename, err) + } + meta, err = f.store.SessionMetadata(t.Context(), f.rootID) + if err != nil || meta.Title != "Renamed without workspace" { + t.Fatalf("rename not persisted: %+v %v", meta, err) + } + // Idempotent retry replays the durable record. + retry, err := client.Command(t.Context(), CommandParams{ + Scope: "root", CommandID: "archive-missing", RootID: f.rootID, Operation: "session.archive", + Payload: json.RawMessage(`{"archived":true}`), + }) + if err != nil || retry.Status != "succeeded" { + t.Fatalf("archive retry %+v %v", retry, err) + } + events, _, err := f.store.ReplayEvents(t.Context(), f.rootID, 0, 100) + if err != nil { + t.Fatal(err) + } + kinds := []string{} + for _, event := range events { + if event.Kind == "session.archived.updated" || event.Kind == "session.title.updated" { + kinds = append(kinds, event.Kind) + } + } + if !reflect.DeepEqual(kinds, []string{"session.archived.updated", "session.title.updated"}) { + t.Fatalf("metadata events = %v", kinds) + } + // Restore the workspace, then a live root still routes through the actor. + if err := f.store.SetWorkingDirectory(f.rootID, t.TempDir()); err != nil { + t.Fatal(err) + } + root, err := f.server.daemon.Open(f.rootID) + if err != nil { + t.Fatal(err) + } + live := clientCommand(t, root, "client", "archive-live", "session.archive", protocol.ArchiveParams{Archived: false}) + if live.Status != "succeeded" { + t.Fatalf("archive live root %+v", live) + } + meta, err = f.store.SessionMetadata(t.Context(), f.rootID) + if err != nil || meta.Archived { + t.Fatalf("live archive not persisted: %+v %v", meta, err) + } +} + func TestClientForkDefaultsToRecognizableTitle(t *testing.T) { f := newV2Fixture(t, &fakeRunner{}) + // Open before the persisted title arrives, as with an asynchronous title + // update. The fork must use store metadata, not the actor's cached name. + if _, err := f.server.daemon.Open(f.rootID); err != nil { + t.Fatal(err) + } if err := f.store.SetTitle(f.rootID, "Original"); err != nil { t.Fatal(err) } @@ -124,4 +267,35 @@ func TestClientForkDefaultsToRecognizableTitle(t *testing.T) { if err != nil || metadata.Title != "Original (fork #1)" || metadata.Archived { t.Fatalf("default fork metadata %+v %v", metadata, err) } + for _, test := range []struct { + name, sourceTitle, customTitle, want string + }{ + {"next fork", "Original", "", "Original (fork #2)"}, + {"updated source", "Session naming cleanup", "", "Session naming cleanup (fork #1)"}, + {"custom name", "Session naming cleanup", "My experiment", "My experiment"}, + } { + t.Run(test.name, func(t *testing.T) { + if err := f.store.SetTitle(f.rootID, test.sourceTitle); err != nil { + t.Fatal(err) + } + payload, err := json.Marshal(map[string]string{"title": test.customTitle, "expected_revision": "0"}) + if err != nil { + t.Fatal(err) + } + result, err := client.Command(t.Context(), CommandParams{ + Scope: "root", CommandID: test.name, RootID: f.rootID, Operation: "session.fork", Payload: payload, + }) + if err != nil || result.Status != "succeeded" { + t.Fatalf("fork %+v %v", result, err) + } + var fork protocol.RootIDResult + if err := json.Unmarshal(result.Result, &fork); err != nil { + t.Fatal(err) + } + metadata, err := f.store.SessionMetadata(t.Context(), fork.RootID) + if err != nil || metadata.Title != test.want || metadata.Archived { + t.Fatalf("fork metadata %+v %v; want %q", metadata, err, test.want) + } + }) + } } diff --git a/internal/daemon/control.go b/internal/daemon/control.go index 62b205b5d..00fd1345e 100644 --- a/internal/daemon/control.go +++ b/internal/daemon/control.go @@ -5,9 +5,11 @@ import ( "encoding/json" "errors" "fmt" + "strings" "github.com/context-labs/whip/internal/agentdef" "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -22,6 +24,7 @@ type Control struct { requests chan controlRequest done chan struct{} store *session.Store + daemon *Daemon deletes chan func() deleteDone chan struct{} } @@ -145,6 +148,115 @@ func (c *Control) ListSessions(ctx context.Context, admission session.CommandAdm return record, err } +var errMetadataRootLive = errors.New("metadata command requires root actor") + +// SessionMetadataCommand mutates cold session metadata without reconstructing +// its runner (the workspace may be gone). The registry check runs on this +// actor, before admission; callers reroute errMetadataRootLive outside it. +// Holding the registry lock through the cold mutation excludes concurrent Open. +func (c *Control) SessionMetadataCommand(ctx context.Context, admission session.CommandAdmission, operation string, payload json.RawMessage, rootID string) (record session.CommandRecord, err error) { + titleChanged := false + err = c.route(ctx, func(actorCtx context.Context) error { + if c.daemon != nil { + c.daemon.mu.Lock() + defer c.daemon.mu.Unlock() + if c.daemon.closing { + return ErrClosed + } + if entry := c.daemon.roots[rootID]; entry != nil { + select { + case <-entry.ready: + if entry.root != nil { + select { + case <-entry.root.Done(): + default: + return errMetadataRootLive + } + } + default: + return errMetadataRootLive + } + } + } + // Daemon scope, like session.delete: root admission enqueues an inbox + // item, which requires the agent row created only by opening the root. + admission.Scope = session.CommandScopeDaemon + admission.RootID = "" + admission.AgentID = "" + admission.Kind = operation + admitted, err := c.store.AdmitCommand(actorCtx, admission) + if err != nil { + return err + } + record = admitted.Command + if !admitted.New { + return nil + } + if err := c.store.SetCommandState(actorCtx, admission.ClientID, admission.CommandID, "running"); err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + var output string + var eventKind string + var event protocol.SessionUpdateEvent + switch operation { + case "session.archive": + var params protocol.ArchiveParams + if err := json.Unmarshal(payload, ¶ms); err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + if err := c.store.SetArchived(actorCtx, rootID, params.Archived); err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + output, err = marshalClientOutput(protocol.ArchiveResult{Archived: params.Archived}, nil) + eventKind = "session.archived.updated" + event.Archived = ¶ms.Archived + case "session.rename": + var params protocol.TitleParams + if err := json.Unmarshal(payload, ¶ms); err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + title := strings.TrimSpace(params.Title) + if title == "" { + return c.finishFailure(actorCtx, admission, errors.New("session title is required"), &record) + } + if err := c.store.SetTitle(rootID, title); err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + titleChanged = true + output, err = marshalClientOutput(protocol.TitleResult{Title: title}, nil) + eventKind = "session.title.updated" + event.Title = title + default: + return c.finishFailure(actorCtx, admission, fmt.Errorf("unsupported metadata command %q", operation), &record) + } + if err == nil { + var eventData []byte + eventData, err = json.Marshal(event) + if err == nil { + _, err = c.store.AppendRootEvent(actorCtx, rootID, eventKind, session.RuntimePayload{ + Data: eventData, MediaType: "application/json", Source: operation, + }) + } + } + if err != nil { + return c.finishFailure(actorCtx, admission, err, &record) + } + record.Outcome, err = c.store.FinishCommand(actorCtx, admission.ClientID, admission.CommandID, "succeeded", session.RuntimePayload{ + Data: []byte(output), MediaType: "application/json", Source: operation, + }) + if err == nil { + record.Status = "succeeded" + } + return err + }) + // Even an event/command-outcome failure cannot undo the committed title. + // route returns ownership only after releasing the registry lock. + if titleChanged && c.daemon != nil { + c.daemon.notifyTitleChanged(rootID) + } + return record, err +} + // AcceptDeleteSession commits admission before asynchronous root shutdown begins. func (c *Control) AcceptDeleteSession(ctx context.Context, admission session.CommandAdmission, rootID string, remove func(context.Context, string) error) (session.CommandRecord, error) { record, _, err := c.deleteSession(ctx, admission, rootID, remove) diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 2453a1a98..cae523ed5 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -33,6 +33,9 @@ type Daemon struct { ctx context.Context cancel context.CancelFunc + titleMu sync.Mutex + titleListeners map[*titleListener]struct{} + mu sync.Mutex wg sync.WaitGroup roots map[string]*rootEntry @@ -59,6 +62,7 @@ func New(store *session.Store, factory Factory, providers ...*ProviderService) ( daemon.providers = providers[0] } daemon.control = newControl(ctx, store) + daemon.control.daemon = daemon return daemon, nil } @@ -83,12 +87,14 @@ func (d *Daemon) Open(rootID string) (*Session, error) { } return d.opened(entry) } - meta, history, err := d.store.Load(rootID) + meta, err := d.store.LoadMeta(rootID) if err != nil { return nil, err } - rootID = meta.ID + return d.openResolved(meta.ID) +} +func (d *Daemon) openResolved(rootID string) (*Session, error) { d.mu.Lock() if d.closing { d.mu.Unlock() @@ -104,7 +110,7 @@ func (d *Daemon) Open(rootID string) (*Session, error) { } return d.opened(entry) } - entry = &rootEntry{ready: make(chan struct{})} + entry := &rootEntry{ready: make(chan struct{})} d.roots[rootID] = entry d.mu.Unlock() @@ -114,6 +120,14 @@ func (d *Daemon) Open(rootID string) (*Session, error) { entry.err = panicError("root construction", value) } }() + // Cold metadata mutations hold the registry lock. Reload after + // publication so construction cannot use a pre-rename snapshot; + // later metadata commands now route to this root instead. + meta, history, err := d.store.Load(rootID) + if err != nil { + entry.err = err + return + } entry.root, entry.err = d.open(meta, history) }() d.mu.Lock() @@ -184,6 +198,34 @@ func (d *Daemon) tombstone(rootID string, entry *rootEntry, root *Session) { d.mu.Unlock() } +// Live returns the already-open root without reconstructing it. Metadata-only +// commands use it to skip opening a cold root whose workspace may be gone. +func (d *Daemon) Live(rootID string) *Session { + d.mu.Lock() + entry := d.roots[rootID] + d.mu.Unlock() + if entry == nil { + return nil + } + select { + case <-entry.ready: + case <-d.ctx.Done(): + return nil + } + d.mu.Lock() + root := entry.root + d.mu.Unlock() + if root == nil { + return nil + } + select { + case <-root.Done(): + return nil + default: + return root + } +} + func (d *Daemon) opened(entry *rootEntry) (*Session, error) { d.mu.Lock() defer d.mu.Unlock() @@ -251,6 +293,7 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err } root = newSession(d.store, meta, authority, components, d.factory) root.providers = d.providers + root.titleChanged = d.notifyTitleChanged root.executors = d.executors root.browserProviders = d.browserProviders // Bind hooks may reconstruct durable child agents through actor-owned diff --git a/internal/daemon/definition_test.go b/internal/daemon/definition_test.go index 08087049f..18dd25c71 100644 --- a/internal/daemon/definition_test.go +++ b/internal/daemon/definition_test.go @@ -101,9 +101,6 @@ func TestDefinitionSurfaceDisablesAutomaticTitle(t *testing.T) { if err != nil { t.Fatal(err) } - if result := clientCommand(t, root, "tui", "autotitle", "session.autotitle", protocol.EmptyParams{}); result.Status != "succeeded" { - t.Fatalf("enable automatic title=%+v", result) - } receipt, err := root.Submit(t.Context(), "Investigate flaky workers") if err != nil { t.Fatal(err) @@ -118,8 +115,8 @@ func TestDefinitionSurfaceDisablesAutomaticTitle(t *testing.T) { if err != nil { t.Fatal(err) } - if strings.Contains(meta.Title, runner.title) { - t.Fatalf("title applied: %q", meta.Title) + if meta.Title != "Investigate flaky workers" { + t.Fatalf("definition opt-out lost deterministic title: %q", meta.Title) } } diff --git a/internal/daemon/input_lifecycle_test.go b/internal/daemon/input_lifecycle_test.go index 528d55d08..11d972f0d 100644 --- a/internal/daemon/input_lifecycle_test.go +++ b/internal/daemon/input_lifecycle_test.go @@ -229,19 +229,16 @@ func TestLifecycleMultipartAndMalformedInput(t *testing.T) { } before := store.RawMessages(rootID) _, receipt, err = root.AdmitCommand(t.Context(), sessionstore.CommandAdmission{ClientID: "client", CommandID: "bad", Kind: "submit.parts", RequestDigest: "bad", Payload: sessionstore.RuntimePayload{Data: []byte(strings.Repeat(" ", 9000) + "{")}}) - if err != nil { - t.Fatal(err) - } - if result := waitReceipt(t, receipt); !errors.Is(result.Err, sessionstore.ErrInvalidInput) { - t.Fatalf("malformed input: %+v", result) + if !errors.Is(err, sessionstore.ErrInvalidInput) || receipt != nil { + t.Fatalf("malformed admission: receipt=%+v error=%v", receipt, err) } after := store.RawMessages(rootID) if len(after) != len(before) || runner.calls.Load() != 1 { t.Fatal("decoding failure reused a journal or invoked the runner") } command, err := store.LoadCommand(t.Context(), "client", "bad") - if err != nil || command.Status != "failed" { - t.Fatalf("bad command: %+v %v", command, err) + if err == nil { + t.Fatalf("rejected input created a command: %+v", command) } next, err := root.Submit(t.Context(), "next valid input") if err != nil { @@ -281,8 +278,8 @@ func TestLifecycleBoundaryRejectsMalformedSteerAndDeliversCompleteInput(t *testi t.Fatal("model did not start") } _, bad, err := root.AdmitCommand(t.Context(), sessionstore.CommandAdmission{ClientID: "client", CommandID: "bad-steer", Kind: "steer.parts", RequestDigest: "bad", Payload: sessionstore.RuntimePayload{Data: []byte("{")}}) - if err != nil { - t.Fatal(err) + if !errors.Is(err, sessionstore.ErrInvalidInput) || bad != nil { + t.Fatalf("malformed steer admission: receipt=%+v error=%v", bad, err) } text := strings.Repeat("x", sessionstore.MaxContentRead) + "STEER_TAIL" good, err := root.Steer(t.Context(), text) @@ -293,9 +290,6 @@ func TestLifecycleBoundaryRejectsMalformedSteerAndDeliversCompleteInput(t *testi if result := waitReceipt(t, receipt); result.Err != nil { t.Fatal(result.Err) } - if result := waitReceipt(t, bad); !errors.Is(result.Err, sessionstore.ErrInvalidInput) { - t.Fatalf("bad steer: %+v", result) - } if result := waitReceipt(t, good); result.Err != nil { t.Fatalf("good steer: %+v", result) } @@ -310,8 +304,8 @@ func TestLifecycleBoundaryRejectsMalformedSteerAndDeliversCompleteInput(t *testi t.Fatalf("full steer missing or incorrect rounds: found=%v calls=%d", found, calls.Load()) } command, err := store.LoadCommand(t.Context(), "client", "bad-steer") - if err != nil || command.Status != "failed" { - t.Fatalf("bad steer command=%+v %v", command, err) + if err == nil { + t.Fatalf("rejected steer created a command: %+v", command) } } diff --git a/internal/daemon/metadata_routing_test.go b/internal/daemon/metadata_routing_test.go new file mode 100644 index 000000000..7cbc8eec1 --- /dev/null +++ b/internal/daemon/metadata_routing_test.go @@ -0,0 +1,161 @@ +package daemon + +import ( + "context" + "encoding/json" + "errors" + "path/filepath" + "sync" + "testing" + "time" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/session" +) + +func TestColdMetadataReroutesAfterRootOpens(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + runner := &titleRunner{ + fakeRunner: &fakeRunner{}, title: "Generated title", + started: make(chan struct{}), release: make(chan struct{}), finished: make(chan struct{}), + } + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: runner}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + changes := observeTitleChanges(t, owner) + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + + // Capture the command after the server chooses its cold route, but before + // daemon control executes it. Open/submit then wins the registry race. + waiting, captured, release := make(chan struct{}), make(chan struct{}), make(chan struct{}) + var releaseOnce sync.Once + unblock := func() { releaseOnce.Do(func() { close(release) }) } + t.Cleanup(unblock) + blocked := make(chan error, 1) + go func() { + blocked <- owner.control.route(ctx, func(actorCtx context.Context) error { + close(waiting) + select { + case request := <-owner.control.requests: + close(captured) + select { + case <-release: + case <-ctx.Done(): + } + request.done <- request.work(actorCtx) + return nil + case <-ctx.Done(): + return ctx.Err() + } + }) + }() + select { + case <-waiting: + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + server := &Server{daemon: owner, ctx: ctx} + connection := &serverConn{client: InitializeParams{ClientID: "metadata-routing"}} + params := CommandParams{ + Scope: "root", RootID: rootID, CommandID: "same-value-rename", + Operation: "session.rename", Payload: json.RawMessage(`{"title":"First question about naming"}`), + } + commandDone := make(chan error, 1) + go func() { + _, err := server.command(connection, params) + commandDone <- err + }() + select { + case <-captured: + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + receipt, err := root.Submit(ctx, "First question about naming") + if err != nil { + t.Fatal(err) + } + waitReceipt(t, receipt) + select { + case <-runner.started: + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + unblock() + select { + case err := <-commandDone: + if err != nil { + t.Fatal(err) + } + case <-ctx.Done(): + t.Fatal("metadata command blocked the daemon actor") + } + if err := <-blocked; err != nil { + t.Fatal(err) + } + if err := root.routeControl(ctx, func(context.Context) error { + if root.titleWork != nil { + return errors.New("same-value rename did not invalidate automatic title") + } + return nil + }); err != nil { + t.Fatal(err) + } + select { + case <-runner.finished: + case <-ctx.Done(): + t.Fatal("manual rename did not cancel title request") + } + record, err := store.LoadCommand(ctx, connection.client.ClientID, params.CommandID) + if err != nil || record.Scope != session.CommandScopeRoot || record.Status != "succeeded" { + t.Fatalf("rerouted admission = %+v, %v", record, err) + } + meta, err := store.SessionMetadata(ctx, rootID) + if err != nil || meta.Title != "First question about naming" { + t.Fatalf("manual title = %+v, %v", meta, err) + } + assertTitleChanges(t, changes, rootID, rootID) // Initial title and rerouted rename, no stale generation. +} + +func TestOpenReloadsMetadataAfterRegistryPublication(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + constructed := make(chan session.Meta, 1) + owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + constructed <- meta + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + // This is Open's initial ID-resolution read, before it publishes the entry. + stale, err := store.LoadMeta(rootID) + if err != nil { + t.Fatal(err) + } + payload := json.RawMessage(`{"title":"Cold rename"}`) + _, err = owner.control.SessionMetadataCommand(t.Context(), session.CommandAdmission{ + ClientID: "metadata-routing", CommandID: "cold-rename", RequestDigest: "cold-rename", + Payload: session.RuntimePayload{Data: payload}, + }, "session.rename", payload, rootID) + if err != nil { + t.Fatal(err) + } + root, err := owner.openResolved(stale.ID) + if err != nil { + t.Fatal(err) + } + if meta := <-constructed; meta.Title != "Cold rename" || root.meta.Title != meta.Title { + t.Fatalf("constructed stale metadata: factory=%q actor=%q", meta.Title, root.meta.Title) + } +} diff --git a/internal/daemon/model_accounting_acceptance_test.go b/internal/daemon/model_accounting_acceptance_test.go index 49be23413..f98b6c95c 100644 --- a/internal/daemon/model_accounting_acceptance_test.go +++ b/internal/daemon/model_accounting_acceptance_test.go @@ -79,7 +79,7 @@ func modelAccountingRuntimeAt(t *testing.T, path string, handler http.HandlerFun if err != nil { return Components{}, err } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) @@ -557,8 +557,11 @@ func TestModelAccountingAcceptanceAutomaticAndUnfundedTitles(t *testing.T) { value.CompactClient, value.CompactModel, value.CompactProvider = value.Client, "title-model", "title-provider" value.CompactPricing = llm.Pricing{Prompt: "0.1", Completion: "0.2"} }) - if result := clientCommand(t, root, "tui", "enable-title", "session.autotitle", protocol.EmptyParams{}); result.Status != "succeeded" { - t.Fatalf("enable title: %+v", result) + if err := root.routeControl(t.Context(), func(context.Context) error { + root.definition.Surface.AutoTitle = true + return nil + }); err != nil { + t.Fatal(err) } receipt, err := root.Submit(t.Context(), "Inspect model accounting") if err != nil || waitReceipt(t, receipt).Err != nil { @@ -585,7 +588,7 @@ func TestModelAccountingAcceptanceAutomaticAndUnfundedTitles(t *testing.T) { if err := store.SetBudgetLimit(t.Context(), root.ID(), "", session.BudgetTokens, 31); err != nil { t.Fatal(err) } - if _, _, err := runtime.rootNode.GenerateTitle(t.Context()); err == nil { + if _, _, err := runtime.rootNode.GenerateTitle(t.Context(), "Inspect model accounting"); err == nil { t.Fatal("unfunded title made a provider request") } if titleRequests.Load() != 1 { diff --git a/internal/daemon/permission_mode_test.go b/internal/daemon/permission_mode_test.go index c7f6e61f3..23534a4ce 100644 --- a/internal/daemon/permission_mode_test.go +++ b/internal/daemon/permission_mode_test.go @@ -285,7 +285,7 @@ func TestPermissionModeRestoresChildrenBeforeResumedWork(t *testing.T) { firstModes.LoadOrStore(node.id, node.ExternalPermissionsEnabled()) observeRunTurn(runs)(node) }) - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) diff --git a/internal/daemon/prompt_test.go b/internal/daemon/prompt_test.go index e0053b60b..a48ef823b 100644 --- a/internal/daemon/prompt_test.go +++ b/internal/daemon/prompt_test.go @@ -399,6 +399,7 @@ func openPromptRuntime(t *testing.T, store *session.Store, rootID string, client if err != nil { return Components{}, err } + definition.Surface.AutoTitle = false runtime, err = NewRecursiveRuntime(RecursiveRuntimeOptions{ Engine: meta.ExecutionEngine, Definition: definition, Agent: value, History: history, Limits: limits, Kernels: rlm.NewManager(limits.MaxWorkers), KernelCommand: recursiveKernelCommand, }) diff --git a/internal/daemon/provider_connections_test.go b/internal/daemon/provider_connections_test.go index fb940bcfe..d87e3038a 100644 --- a/internal/daemon/provider_connections_test.go +++ b/internal/daemon/provider_connections_test.go @@ -473,7 +473,7 @@ func TestProviderDisableBlocksRetainedRootChildAndHelperClients(t *testing.T) { if _, _, err := runtime.rootNode.complete(t.Context(), "helper", 128); !llm.IsPermanentRequestError(err) { t.Fatalf("helper bypassed disable: %v", err) } - if _, _, err := runtime.rootNode.GenerateTitle(t.Context()); !llm.IsPermanentRequestError(err) { + if _, _, err := runtime.rootNode.GenerateTitle(t.Context(), "Inspect model accounting"); !llm.IsPermanentRequestError(err) { t.Fatalf("compact/title route bypassed disable: %v", err) } if requests.Load() != 1 || runTurnCount(runs, id) != 1 { diff --git a/internal/daemon/recursive_runtime_test.go b/internal/daemon/recursive_runtime_test.go index f81bf5a7b..37ecf7423 100644 --- a/internal/daemon/recursive_runtime_test.go +++ b/internal/daemon/recursive_runtime_test.go @@ -76,7 +76,7 @@ func openRecursiveRuntime(t *testing.T, client *llm.Client, maxWorkers int, engi if runtimeErr != nil { return Components{}, runtimeErr } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) @@ -471,7 +471,7 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { if runtimeErr != nil { return Components{}, runtimeErr } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) @@ -572,7 +572,7 @@ func TestQueuedInitialAgentPromptSurvivesRestartExactlyOnce(t *testing.T) { if runtimeErr != nil { return Components{}, runtimeErr } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if ownerErr != nil { t.Fatal(ownerErr) @@ -907,7 +907,7 @@ func TestChildScratchSurvivesDaemonRestart(t *testing.T) { if runtimeErr != nil { return Components{}, runtimeErr } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if ownerErr != nil { t.Fatal(ownerErr) diff --git a/internal/daemon/report_restore_test.go b/internal/daemon/report_restore_test.go index f03e9f2a2..e122821d1 100644 --- a/internal/daemon/report_restore_test.go +++ b/internal/daemon/report_restore_test.go @@ -47,7 +47,7 @@ func TestReportModeRestoresIdentityAndCompletionBehavior(t *testing.T) { if err != nil { return Components{}, err } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) diff --git a/internal/daemon/runtime_parity_test.go b/internal/daemon/runtime_parity_test.go index 24d518c77..834ee8911 100644 --- a/internal/daemon/runtime_parity_test.go +++ b/internal/daemon/runtime_parity_test.go @@ -43,7 +43,7 @@ func TestRuntimeRegistryEveryOperationOverUnixRPC(t *testing.T) { "session.effort": {`{"effort":"off","persist_default":false}`, false}, "session.effort.get": {`{}`, false}, "session.model": {`{"model":"replacement","provider":"provider","persist_default":false}`, false}, "session.model.get": {`{}`, false}, "session.list": {`{"limit":10}`, false}, "session.open": {`{"id":"$ROOT"}`, false}, "session.rename": {`{"title":"renamed"}`, false}, - "session.reload": {`{}`, false}, "session.autotitle": {`{}`, false}, "run.configure": {`{"max_turns":2}`, true}, + "session.reload": {`{}`, false}, "run.configure": {`{"max_turns":2}`, true}, "history.clear": {`{}`, false}, "history.rewind": {`{"cut":2,"expected_revision":"0"}`, false}, "history.compact": {`{}`, true}, "history.compact.log": {`{}`, false}, "history.compact.retry": {`{}`, false}, "compaction.configure": {`{}`, false}, "history.user.list": {`{}`, false}, "session.preview": {`{"id":"$ROOT"}`, false}, "agents.list": {`{}`, false}, "agent.transcript": {`{"id":"$ROOT"}`, false}, diff --git a/internal/daemon/server.go b/internal/daemon/server.go index fecbbbd1f..a4a3b3af0 100644 --- a/internal/daemon/server.go +++ b/internal/daemon/server.go @@ -54,6 +54,7 @@ type Server struct { listener net.Listener gatewayStatus protocol.GatewayStatus runtimeID string + unlistenTitle func() mu sync.Mutex clients map[*serverConn]struct{} @@ -77,6 +78,9 @@ type serverConn struct { out chan []byte inFlight chan struct{} + // Guarded by server.mu; true only after the initialize response is written. + titleNotifications bool + mu sync.Mutex outBytes int64 lifecycle int64 @@ -123,12 +127,14 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { if providers == nil { providers = NewProviderService(ctx, strconv.FormatInt(options.Generation, 10)) } - return &Server{ + server := &Server{ daemon: value, options: options, ctx: ctx, cancel: cancel, runtimeID: runtimeID, providers: providers, clients: make(map[*serverConn]struct{}), slots: make(chan struct{}, options.MaxConnections), uploads: newUploadManager(value.store, options.RuntimeDir), gatewayStatus: protocol.GatewayStatus{State: "disabled"}, - }, nil + } + server.unlistenTitle = value.listenTitleChanges(server.notifyTitleChanged) + return server, nil } func (s *Server) ListenAndServe(paths RuntimePaths) error { @@ -186,6 +192,7 @@ func (s *Server) Close() error { s.daemon.browserProviders.shutdown() s.lifeMu.Lock() s.closed.Store(true) + s.unlistenTitle() s.cancel() if s.listener != nil { err = s.listener.Close() @@ -250,7 +257,7 @@ func (s *Server) serveTransport(raw messageTransport, network bool) { } defer s.unregister(connection) _ = raw.SetReadDeadline(time.Time{}) - capabilities := []string{"commands", "events", "snapshots", "uploads", "permissions", "history_pages", "collections", "host_configuration", "workspace_completion", "host_skill_completion", "host_global_skill_completion", "skill_catalog_completion", "host_views", "themes", "mailbox_inspection", "input_attachments", "session_summaries", "execution_engines", "terminals", "desktop-browser-v1", "desktop-browser-v2", protocol.NetworkClientCapability} + capabilities := []string{"commands", "events", "snapshots", "uploads", "permissions", "history_pages", "collections", "host_configuration", "workspace_completion", "host_skill_completion", "host_global_skill_completion", "skill_catalog_completion", "host_views", "themes", "mailbox_inspection", "input_attachments", "session_summaries", "execution_engines", "terminals", "desktop-browser-v1", "desktop-browser-v2", protocol.NetworkClientCapability, protocol.SessionTitleNotificationsCapability} negotiated := []string{} for _, feature := range initialize.Capabilities { if slices.Contains(capabilities, feature) && !slices.Contains(negotiated, feature) { @@ -270,6 +277,9 @@ func (s *Server) serveTransport(raw messageTransport, network bool) { if !s.goWorker(connection.writeLoop) { return } + s.mu.Lock() + connection.titleNotifications = slices.Contains(negotiated, protocol.SessionTitleNotificationsCapability) + s.mu.Unlock() for { _ = raw.SetReadDeadline(time.Now().Add(s.options.ClientIdleTimeout)) @@ -652,6 +662,19 @@ func (s *Server) command(connection *serverConn, params CommandParams) (CommandR if params.Scope != string(session.CommandScopeRoot) { return CommandResult{}, errors.New("command scope must be daemon or root") } + if params.Operation == "session.archive" || params.Operation == "session.rename" { + if root := s.daemon.Live(params.RootID); root == nil { + record, err := s.daemon.control.SessionMetadataCommand(s.ctx, session.CommandAdmission{ + ClientID: connection.client.ClientID, CommandID: params.CommandID, RequestDigest: digest, + Payload: session.RuntimePayload{Data: params.Payload, MediaType: "application/json", Source: params.Operation}, + }, params.Operation, params.Payload, params.RootID) + if !errors.Is(err, errMetadataRootLive) { + return s.commandRecordResult(s.ctx, record, err) + } + // The root opened while this command waited for daemon control. + // No command was admitted; route it below outside that actor. + } + } root, err := s.daemon.Open(params.RootID) if err != nil { return CommandResult{}, err diff --git a/internal/daemon/session.go b/internal/daemon/session.go index 522d6b2ef..6bbd17110 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -5,10 +5,12 @@ import ( "encoding/json" "errors" "fmt" + "log/slog" "runtime/debug" "slices" "sync" "time" + "unicode/utf8" "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/agentdef" @@ -96,6 +98,7 @@ const ( workerControl = "control" workerClientCommand = "client.command" workerStream = "stream" + workerTitle = "title" ) type workerCompletion struct { @@ -172,6 +175,7 @@ type workerEnvelope struct { at time.Time client *clientCommandCompletion stream *streamEnvelope + title *titleWork } type streamEnvelope struct { @@ -278,6 +282,7 @@ func (s *supervisor) wait() { } type Session struct { + titleChanged func(string) providers *ProviderService store *sessionstore.Store meta sessionstore.Meta @@ -314,8 +319,7 @@ type Session struct { clientIntegrations int clientPreparing bool reloadPending bool - titleAttempted bool - autoTitle bool + titleWork *titleWork deferredWake time.Time accountingMu sync.Mutex @@ -378,14 +382,18 @@ func (s *Session) Submit(ctx context.Context, text string) (*Receipt, error) { if s.meta.Kind != sessionstore.SessionKindAgent { return nil, errors.New("tool-host sessions cannot submit model turns") } - return s.enqueue(ctx, "submit", text, true) + return routeControlValue(s, ctx, func(actorCtx context.Context) (*Receipt, error) { + return s.enqueue(actorCtx, "submit", text, true) + }) } func (s *Session) Steer(ctx context.Context, text string) (*Receipt, error) { if s.meta.Kind != sessionstore.SessionKindAgent { return nil, errors.New("tool-host sessions cannot steer model turns") } - return s.enqueue(ctx, "steer", text, true) + return routeControlValue(s, ctx, func(actorCtx context.Context) (*Receipt, error) { + return s.enqueue(actorCtx, "steer", text, true) + }) } // AdmitCommand binds one stable protocol command to the root actor's durable @@ -415,6 +423,7 @@ func (s *Session) admitCommand(ctx context.Context, admission sessionstore.Comma return admittedCommand{}, err } if result.New { + s.initializeTitle(result.TitleInitialization) s.notify() } if !wait { @@ -481,14 +490,21 @@ func (s *Session) enqueue(ctx context.Context, kind, text string, receipt bool) s.admitMu.RUnlock() return nil, ErrStopped } + origin := "internal" + if receipt { + origin = "client" + } sequence, err := s.store.EnqueueInbox(ctx, sessionstore.InboxEnqueue{ - RootID: s.meta.ID, AgentID: s.authority.AgentID, Kind: kind, + RootID: s.meta.ID, AgentID: s.authority.AgentID, Kind: kind, Origin: origin, Payload: sessionstore.RuntimePayload{Data: []byte(text), MediaType: "text/plain", Source: kind}, }) if err != nil { s.admitMu.RUnlock() return nil, err } + if receipt { + s.initializeTitle(sequence.TitleInitialization) + } var result *Receipt if receipt { result = newReceipt(sequence.InboxSeq) @@ -758,6 +774,8 @@ func (s *Session) handleWorkerEvent(event *workerEnvelope) error { return s.recordStreamEvent(event.stream) case workerScheduleTick: return s.fireDueSchedules(event.at) + case workerTitle: + s.completeTitle(event.title) case workerTurn: return s.completeTurn(event.completion) } @@ -1058,9 +1076,6 @@ func (s *Session) completeTurn(completion workerCompletion) error { if current.seq > 0 { s.settle(current.seq, Completion{Sequence: current.seq, Output: completion.output, Err: completion.err}) } - if completion.err == nil { - s.maybeGenerateTitle() - } s.startPendingReload() return nil } @@ -1072,36 +1087,92 @@ func (s *Session) applyPendingReloadAfterAgent() { }) } -func (s *Session) maybeGenerateTitle() { - if !s.autoTitle || s.titleAttempted || s.meta.Kind != sessionstore.SessionKindAgent || !s.definition.Surface.AutoTitle { +type titleWork struct { + cancel context.CancelFunc + placeholder string + title string + err error +} + +// initializeTitle runs only for the admission that committed the fallback. +func (s *Session) initializeTitle(initial *sessionstore.TitleInitialization) { + if initial == nil { + return + } + ctx, cancel := context.WithTimeout(s.supervisor.ctx, 5*time.Second) + defer cancel() + if err := s.publishTitle(ctx, initial.Title); err != nil { + slog.Warn("publish initial session title", "root_id", s.meta.ID, "error", err) + } + if !s.definition.Surface.AutoTitle || utf8.RuneCountInString(initial.Title) < 20 { return } runner, ok := s.runner.(interface { - GenerateTitle(context.Context) (string, llm.Usage, error) + GenerateTitle(context.Context, string) (string, llm.Usage, error) }) if !ok { return } - meta, history, err := s.store.Load(s.meta.ID) - if err != nil { - return + generate := func(ctx context.Context) (string, llm.Usage, error) { + return runner.GenerateTitle(ctx, initial.Prompt) } - placeholder := sessionstore.ProvisionalTitle(history) - if placeholder == "" || meta.Title != placeholder { - s.titleAttempted = true - return + if prepared, ok := s.runner.(interface { + prepareTitle(string) func(context.Context) (string, llm.Usage, error) + }); ok { + generate = prepared.prepareTitle(initial.Prompt) } - s.titleAttempted = true - s.supervisor.launchWorker("automatic session title", func() { - ctx, cancel := context.WithTimeout(s.supervisor.ctx, 20*time.Second) - defer cancel() - title, _, titleErr := runner.GenerateTitle(ctx) - if titleErr == nil { - if changed, _ := s.store.SetTitleIf(s.meta.ID, placeholder, title); changed { - s.emitSessionUpdate(ctx, "session.title.updated", SessionUpdateEvent{Title: title}) + modelCtx, stop := context.WithTimeout(s.supervisor.ctx, 20*time.Second) + work := &titleWork{cancel: stop, placeholder: initial.Title} + s.titleWork = work + if !s.supervisor.launchWorker("automatic session title", func() { + defer stop() + defer func() { + if value := recover(); value != nil { + work.err = panicError("automatic session title", value) } - } + s.supervisor.post(workerEnvelope{kind: workerTitle, title: work}) + }() + work.title, _, work.err = generate(modelCtx) + }) { + stop() + s.titleWork = nil + } +} + +func (s *Session) completeTitle(work *titleWork) { + if work == nil || s.titleWork != work { + return // An explicit rename invalidates even a same-value title. + } + s.titleWork = nil + work.cancel() + if work.err != nil { + slog.Warn("generate session title", "root_id", s.meta.ID, "error", work.err) + return + } + // Persistence has its own deadline, not the spent model-call deadline. + ctx, cancel := context.WithTimeout(s.supervisor.ctx, 5*time.Second) + defer cancel() + changed, err := s.store.SetTitleIfContext(ctx, s.meta.ID, work.placeholder, work.title) + if err == nil && changed { + err = s.publishTitle(ctx, work.title) + } + if err != nil { + slog.Warn("save generated session title", "root_id", s.meta.ID, "error", err) + } +} + +// publishTitle is shared with manual rename; callers commit before publishing. +func (s *Session) publishTitle(ctx context.Context, title string) error { + s.meta.Title = title + s.notifyTitleChanged(s.meta.ID) + payload, err := json.Marshal(SessionUpdateEvent{Title: title}) + if err != nil { + return err + } + _, err = s.store.AppendRootEvent(ctx, s.meta.ID, "session.title.updated", sessionstore.RuntimePayload{ + Data: payload, MediaType: "application/json", Source: "session.title.updated", }) + return err } func (s *Session) finish(err error) { diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index 809c6c44b..4d682c145 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -16,13 +16,20 @@ import ( "time" "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/agentdef" "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" ) +// withoutAutomaticTitle isolates conversation-only fixtures from background model calls. +func withoutAutomaticTitle() agentdef.Definition { + definition := agentdef.Coding() + definition.Surface.AutoTitle = false + return definition +} + type fakeRunner struct { mu sync.Mutex history []llm.Message @@ -41,7 +48,10 @@ type titleRunner struct { finished chan struct{} } -func (r *titleRunner) GenerateTitle(ctx context.Context) (string, llm.Usage, error) { +func (r *titleRunner) GenerateTitle(ctx context.Context, _ string) (string, llm.Usage, error) { + if r.finished != nil { + defer close(r.finished) + } if r.started != nil { close(r.started) } @@ -52,9 +62,6 @@ func (r *titleRunner) GenerateTitle(ctx context.Context) (string, llm.Usage, err return "", llm.Usage{}, ctx.Err() } } - if r.finished != nil { - close(r.finished) - } return r.title, llm.Usage{PromptTokens: 2, CompletionTokens: 1}, nil } @@ -169,9 +176,6 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { if err != nil { t.Fatal(err) } - if result := clientCommand(t, root, "tui", "autotitle", "session.autotitle", protocol.EmptyParams{}); result.Status != "succeeded" { - t.Fatalf("enable automatic title=%+v", result) - } receipt, err := root.Submit(t.Context(), "Investigate flaky workers") if err != nil { t.Fatal(err) @@ -222,9 +226,6 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { if err != nil { t.Fatal(err) } - if result := clientCommand(t, root, "tui", "autotitle", "session.autotitle", protocol.EmptyParams{}); result.Status != "succeeded" { - t.Fatalf("enable automatic title=%+v", result) - } receipt, err := root.Submit(t.Context(), strings.Repeat("界", 65)) if err != nil { t.Fatal(err) @@ -267,7 +268,6 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { if err != nil { t.Fatal(err) } - clientCommand(t, root, "tui", "autotitle", "session.autotitle", protocol.EmptyParams{}) receipt, err := root.Submit(t.Context(), "Investigate flaky workers") if err != nil { t.Fatal(err) @@ -750,7 +750,7 @@ func TestToolPanicReentersRootSupervisor(t *testing.T) { Run: func(context.Context, json.RawMessage) (string, error) { panic("tool exploded") }, }) daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { - return Components{Runner: &AgentSession{agent: ag}}, nil + return Components{Runner: &AgentSession{agent: ag}, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) @@ -790,7 +790,7 @@ func TestAgentStreamEventsAreDurableOrderedAndSnapshotRestorable(t *testing.T) { rootID := createRoot(t, store) agentValue := agent.NewRuntime(llm.New(server.URL, "key"), "model", 100, "system", tools.NewServices()) value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { - return Components{Runner: &AgentSession{agent: agentValue}}, nil + return Components{Runner: &AgentSession{agent: agentValue}, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) @@ -870,7 +870,7 @@ func TestOpenBindsMCPProcesses(t *testing.T) { ag := agent.NewRuntime(llm.New("http://unused", "key"), "model", 100, "system", tools.NewServices()) manager := &fakeMCP{} daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { - return Components{Runner: &AgentSession{agent: ag}, MCP: manager}, nil + return Components{Runner: &AgentSession{agent: ag}, MCP: manager, Definition: withoutAutomaticTitle()}, nil }) if err != nil { t.Fatal(err) diff --git a/internal/daemon/subscription_runtime_test.go b/internal/daemon/subscription_runtime_test.go index 370c0cba6..9c7766891 100644 --- a/internal/daemon/subscription_runtime_test.go +++ b/internal/daemon/subscription_runtime_test.go @@ -102,7 +102,7 @@ func TestSubscriptionRecursiveRuntimeToolsHelpersTitleAndCompaction(t *testing.T if err != nil { return Components{}, err } - return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind}, nil + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: withoutAutomaticTitle()}, nil }, providers) if err != nil { t.Fatal(err) @@ -137,7 +137,7 @@ func TestSubscriptionRecursiveRuntimeToolsHelpersTitleAndCompaction(t *testing.T if child.agent.Provider != openaiauth.Provider || child.agent.Client.HTTP != client.HTTP { t.Fatal("child lost the shared subscription credential owner") } - if title, _, err := runtime.rootNode.GenerateTitle(t.Context()); err != nil || title != "subscription result" { + if title, _, err := runtime.rootNode.GenerateTitle(t.Context(), "Inspect model accounting"); err != nil || title != "subscription result" { t.Fatalf("subscription title: %q %v", title, err) } if _, err := runtime.rootNode.CompactNow(t.Context()); err != nil { diff --git a/internal/daemon/title_lifecycle_test.go b/internal/daemon/title_lifecycle_test.go new file mode 100644 index 000000000..66934d594 --- /dev/null +++ b/internal/daemon/title_lifecycle_test.go @@ -0,0 +1,560 @@ +package daemon + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/http/httptest" + "path/filepath" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/session" + "github.com/context-labs/whip/internal/tools" +) + +type lifecycleTitleRunner struct { + *fakeRunner + generate func(context.Context, string) (string, llm.Usage, error) + titles atomic.Int32 +} + +func (r *lifecycleTitleRunner) GenerateTitle(ctx context.Context, prompt string) (string, llm.Usage, error) { + r.titles.Add(1) + return r.generate(ctx, prompt) +} + +func openTitleLifecycle(t *testing.T, store *session.Store, rootID string, runner Runner) (*Daemon, *Session) { + t.Helper() + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: runner}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + return owner, root +} + +func waitTitleLifecycle(t *testing.T, signal <-chan struct{}) { + t.Helper() + select { + case <-signal: + case <-time.After(5 * time.Second): + t.Fatal("title lifecycle did not reach expected state") + } +} + +func settleTitleLifecycle(t *testing.T, root *Session) { + t.Helper() + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + for { + idle, err := routeControlValue(root, ctx, func(context.Context) (bool, error) { + return root.titleWork == nil && root.running == nil, nil + }) + if err != nil { + t.Fatal(err) + } + if idle { + if err := root.routeControl(ctx, func(context.Context) error { return nil }); err != nil { + t.Fatal(err) + } + return + } + select { + case <-ctx.Done(): + t.Fatal(ctx.Err()) + case <-time.After(time.Millisecond): + } + } +} + +func assertTitleLifecycle(t *testing.T, store *session.Store, rootID, want string) { + t.Helper() + meta, _, err := store.Load(rootID) + if err != nil || meta.Title != want { + t.Fatalf("persisted title=%q, want %q, error=%v", meta.Title, want, err) + } +} + +func TestTitleLifecycleKeepsShortDeterministicTitles(t *testing.T) { + for _, test := range []struct { + name, prompt, deterministic string + wantCalls int32 + }{ + {"short", "Session naming", "Session naming", 0}, + {"19 characters", strings.Repeat("x", 19), strings.Repeat("x", 19), 0}, + {"20 characters", strings.Repeat("x", 20), strings.Repeat("x", 20), 1}, + {"19 Unicode characters", strings.Repeat("界", 19), strings.Repeat("界", 19), 0}, + {"20 Unicode characters", strings.Repeat("界", 20), strings.Repeat("界", 20), 1}, + {"normalized whitespace", " Session" + strings.Repeat(" ", 30) + "naming ", "Session naming", 0}, + } { + t.Run(test.name, func(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + t.Cleanup(func() { _ = store.Close() }) + rootID := createRoot(t, store) + runner := &lifecycleTitleRunner{ + fakeRunner: &fakeRunner{}, + generate: func(context.Context, string) (string, llm.Usage, error) { + return "Generated title", llm.Usage{}, nil + }, + } + _, root := openTitleLifecycle(t, store, rootID, runner) + receipt, err := root.Submit(t.Context(), test.prompt) + if err != nil { + t.Fatal(err) + } + if result := waitReceipt(t, receipt); result.Err != nil { + t.Fatal(result.Err) + } + settleTitleLifecycle(t, root) + want := test.deterministic + if test.wantCalls != 0 { + want = "Generated title" + } + assertTitleLifecycle(t, store, rootID, want) + // A later long message must not reconsider an intentionally short title. + receipt, err = root.Submit(t.Context(), "A much longer follow-up message about this session") + if err != nil { + t.Fatal(err) + } + if result := waitReceipt(t, receipt); result.Err != nil { + t.Fatal(result.Err) + } + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, want) + if runner.titles.Load() != test.wantCalls { + t.Fatalf("title calls = %d, want %d", runner.titles.Load(), test.wantCalls) + } + }) + } +} + +func TestTitleLifecycleAdmissionPrecedesTurnAndDeduplicates(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + t.Cleanup(func() { _ = store.Close() }) + rootID := createRoot(t, store) + started, release := make(chan struct{}), make(chan struct{}) + unblock := sync.OnceFunc(func() { close(release) }) + runner := &lifecycleTitleRunner{fakeRunner: &fakeRunner{}} + runner.generate = func(ctx context.Context, prompt string) (string, llm.Usage, error) { + if prompt != "Investigate flaky workers" { + t.Errorf("title prompt=%q", prompt) + } + close(started) + select { + case <-release: + return "Worker Queue Investigation", llm.Usage{}, nil + case <-ctx.Done(): + return "", llm.Usage{}, ctx.Err() + } + } + _, root := openTitleLifecycle(t, store, rootID, runner) + t.Cleanup(unblock) + assertTitleLifecycle(t, store, rootID, "") + if runner.titles.Load() != 0 { + t.Fatal("opening an unused session requested a title") + } + if err := root.routeControl(t.Context(), func(context.Context) error { + root.clientBusy = true + return nil + }); err != nil { + t.Fatal(err) + } + admission := session.CommandAdmission{ + ClientID: "title-client", CommandID: "first", Kind: "submit", Operation: "submit", RequestDigest: "first", + Payload: session.RuntimePayload{Data: []byte("Investigate flaky workers")}, + } + accepted, receipt, err := root.AdmitCommand(t.Context(), admission) + if err != nil || !accepted.New { + t.Fatalf("admission=%+v, error=%v", accepted, err) + } + assertTitleLifecycle(t, store, rootID, "Investigate flaky workers") + waitTitleLifecycle(t, started) + if runner.calls.Load() != 0 { + t.Fatal("conversation ran while dispatch was blocked") + } + duplicate, _, err := root.AdmitCommand(t.Context(), admission) + if err != nil || duplicate.New { + t.Fatalf("duplicate=%+v, error=%v", duplicate, err) + } + unblock() + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, "Worker Queue Investigation") + if runner.calls.Load() != 0 { + t.Fatal("generated title needed a conversation turn") + } + events, _, err := store.ReplayEvents(t.Context(), rootID, 0, session.MaxEventReplay) + if err != nil { + t.Fatal(err) + } + var titles []string + for _, event := range events { + if event.Kind == "session.title.updated" { + var update SessionUpdateEvent + if err := json.Unmarshal(event.Payload.Inline, &update); err != nil { + t.Fatal(err) + } + titles = append(titles, update.Title) + } + } + if fmt.Sprint(titles) != "[Investigate flaky workers Worker Queue Investigation]" { + t.Fatalf("title publication order=%q", titles) + } + if err := root.routeControl(t.Context(), func(context.Context) error { + root.clientBusy = false + return nil + }); err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatal(completion.Err) + } + later, err := root.Submit(t.Context(), "A later user message") + if err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, later); completion.Err != nil { + t.Fatal(completion.Err) + } + settleTitleLifecycle(t, root) + if runner.titles.Load() != 1 || runner.calls.Load() != 2 { + t.Fatalf("title calls=%d, conversation calls=%d", runner.titles.Load(), runner.calls.Load()) + } +} + +func TestTitleLifecycleFailureKeepsFallbackWithoutRestartRetry(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + runner := &lifecycleTitleRunner{ + fakeRunner: &fakeRunner{}, + generate: func(context.Context, string) (string, llm.Usage, error) { + return "", llm.Usage{}, errors.New("title provider unavailable") + }, + } + owner, root := openTitleLifecycle(t, store, rootID, runner) + receipt, err := root.Submit(t.Context(), "Keep the fallback title") + if err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatalf("title failure failed the conversation: %v", completion.Err) + } + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, "Keep the fallback title") + if runner.titles.Load() != 1 { + t.Fatalf("title attempts=%d", runner.titles.Load()) + } + if err := owner.Close(); err != nil { + t.Fatal(err) + } + if err := store.Close(); err != nil { + t.Fatal(err) + } + store = openStore(t, path) + t.Cleanup(func() { _ = store.Close() }) + restarted := &lifecycleTitleRunner{fakeRunner: &fakeRunner{}, generate: runner.generate} + _, root = openTitleLifecycle(t, store, rootID, restarted) + receipt, err = root.Submit(t.Context(), "Do not try naming again") + if err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatal(completion.Err) + } + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, "Keep the fallback title") + if restarted.titles.Load() != 0 { + t.Fatalf("restart retried naming %d times", restarted.titles.Load()) + } +} + +func TestTitleLifecycleRenameInvalidatesCompletedResult(t *testing.T) { + for _, names := range [][]string{{"Original user request"}, {"Manual title", "Original user request"}} { + t.Run(strings.Join(names, "/"), func(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + t.Cleanup(func() { _ = store.Close() }) + rootID := createRoot(t, store) + runner := &titleRunner{ + fakeRunner: &fakeRunner{}, title: "Generated Too Late", + started: make(chan struct{}), release: make(chan struct{}), finished: make(chan struct{}), + } + _, root := openTitleLifecycle(t, store, rootID, runner) + unblock := sync.OnceFunc(func() { close(runner.release) }) + t.Cleanup(unblock) + receipt, err := root.Submit(t.Context(), "Original user request") + if err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatal(completion.Err) + } + waitTitleLifecycle(t, runner.started) + if err := root.routeControl(t.Context(), func(ctx context.Context) error { + // Finish the provider while the actor is held, then rename before it + // can process the completed title event. Cancellation cannot save us. + unblock() + deadline := time.Now().Add(5 * time.Second) + for { + root.supervisor.mu.Lock() + posted := false + for _, event := range root.supervisor.events { + posted = posted || event.kind == workerTitle + } + root.supervisor.mu.Unlock() + if posted { + break + } + if time.Now().After(deadline) { + return errors.New("title result did not reach the actor") + } + time.Sleep(time.Millisecond) + } + for _, name := range names { + raw, _ := json.Marshal(map[string]string{"title": name}) + if _, err := root.applyClientCommand(ctx, "session.rename", raw); err != nil { + return err + } + } + return nil + }); err != nil { + t.Fatal(err) + } + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, "Original user request") + }) + } +} + +func TestTitleLifecycleOutlivesConversationFailureAndCancellation(t *testing.T) { + for _, cancelTurn := range []bool{false, true} { + t.Run(fmt.Sprintf("cancel=%t", cancelTurn), func(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + t.Cleanup(func() { _ = store.Close() }) + rootID := createRoot(t, store) + turnStarted := make(chan struct{}) + turnFailure := errors.New("conversation failed") + runner := &titleRunner{ + fakeRunner: &fakeRunner{turn: func(ctx context.Context, _ string, _ bool) (string, error) { + close(turnStarted) + if cancelTurn { + <-ctx.Done() + return "", ctx.Err() + } + return "", turnFailure + }}, + title: "Independent Session Title", started: make(chan struct{}), + release: make(chan struct{}), finished: make(chan struct{}), + } + _, root := openTitleLifecycle(t, store, rootID, runner) + unblock := sync.OnceFunc(func() { close(runner.release) }) + t.Cleanup(unblock) + receipt, err := root.Submit(t.Context(), "Investigate a failed conversation") + if err != nil { + t.Fatal(err) + } + waitTitleLifecycle(t, runner.started) + waitTitleLifecycle(t, turnStarted) + if cancelTurn { + target, err := store.ActiveTurn(t.Context(), rootID, root.AgentID()) + if err != nil { + t.Fatal(err) + } + result := clientCommand(t, root, "title-client", "cancel", "cancel", map[string]string{"turn_id": target}) + if result.Status != "succeeded" { + t.Fatalf("cancel=%+v", result) + } + turnFailure = context.Canceled + } + if completion := waitReceipt(t, receipt); !errors.Is(completion.Err, turnFailure) { + t.Fatalf("conversation error=%v, want %v", completion.Err, turnFailure) + } + select { + case <-runner.finished: + t.Fatal("conversation completion cancelled the title request") + default: + } + unblock() + settleTitleLifecycle(t, root) + assertTitleLifecycle(t, store, rootID, runner.title) + }) + } +} + +func TestTitleLifecycleShutdownAndDeletionJoinWorker(t *testing.T) { + for _, deleting := range []bool{false, true} { + t.Run(fmt.Sprintf("delete=%t", deleting), func(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + t.Cleanup(func() { _ = store.Close() }) + rootID := createRoot(t, store) + started, cancelled, release := make(chan struct{}), make(chan struct{}), make(chan struct{}) + unblock := sync.OnceFunc(func() { close(release) }) + runner := &lifecycleTitleRunner{fakeRunner: &fakeRunner{}} + runner.generate = func(ctx context.Context, _ string) (string, llm.Usage, error) { + close(started) + <-ctx.Done() + close(cancelled) + <-release + return "", llm.Usage{}, ctx.Err() + } + owner, root := openTitleLifecycle(t, store, rootID, runner) + t.Cleanup(unblock) + receipt, err := root.Submit(t.Context(), "Preserve this fallback") + if err != nil { + t.Fatal(err) + } + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatal(completion.Err) + } + waitTitleLifecycle(t, started) + stopped := make(chan error, 1) + go func() { + if deleting { + stopped <- owner.DeleteSession(t.Context(), rootID) + } else { + stopped <- owner.Close() + } + }() + waitTitleLifecycle(t, cancelled) + select { + case err := <-stopped: + t.Fatalf("stop returned before title worker exited: %v", err) + default: + } + unblock() + select { + case err := <-stopped: + if err != nil { + t.Fatal(err) + } + case <-time.After(5 * time.Second): + t.Fatal("stop did not join title worker") + } + if !deleting { + // Daemon.Close owns the store; reopen to check durable fallback. + reopened := openStore(t, path) + t.Cleanup(func() { _ = reopened.Close() }) + assertTitleLifecycle(t, reopened, rootID, "Preserve this fallback") + } else if _, _, err := store.Load(rootID); err == nil { + t.Fatal("deleted session still exists") + } + }) + } +} + +func TestGenerateTitlePromptOnlyAndRouteSnapshot(t *testing.T) { + for _, compact := range []bool{false, true} { + t.Run(fmt.Sprintf("compact=%t", compact), func(t *testing.T) { + requests := make(chan llm.Request, 1) + provider := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + request, ok := modelAccountingRequest(t, w, r) + if !ok { + return + } + if r.Header.Get("Authorization") != "Bearer original-key" { + t.Errorf("request used mutated credentials: %q", r.Header.Get("Authorization")) + } + requests <- request + modelAccountingReply(w, request, "Snapshot Session Title", modelAccountingUsage()) + })) + t.Cleanup(provider.Close) + client := llm.New(provider.URL, "original-key") + client.MaxRetries = 7 + owner := agent.NewRuntime(client, "main-model", 128, "", tools.NewServices()) + wantModel := "main-model" + if compact { + owner.CompactClient, owner.CompactModel = client, "compact-model" + wantModel = "compact-model" + } + // No runtime, kernel, store, or conversation history exists. + runner := &AgentSession{agent: owner} + generate := runner.prepareTitle(" Inspect\n" + strings.Repeat("界", 310)) + client.BaseURL, client.APIKey = "http://127.0.0.1:1", "mutated-key" + owner.Model, owner.CompactModel = "mutated-main", "mutated-compact" + replacement := agent.NewRuntime(client, "replacement", 128, "", tools.NewServices()) + runner.agent = replacement + title, usage, err := generate(t.Context()) + if err != nil || title != "Snapshot Session Title" { + t.Fatalf("title=%q, error=%v", title, err) + } + request := <-requests + wantPrompt := "Inspect " + strings.Repeat("界", 292) + if request.Model != wantModel || request.MaxTokens != 24 || len(request.Messages) != 2 || + request.Messages[0].Role != "system" || request.Messages[1].Role != "user" || + request.Messages[1].Content != wantPrompt { + t.Fatalf("prompt-only snapshot request=%+v", request) + } + for _, instruction := range []string{ + "usually 2–6 words", "Prefer a short noun", "Avoid filler", + "Use sentence case: capitalize only the first word, proper nouns, and", + "abbreviations. Preserve the spelling and casing of technical identifiers.", + "Return only the title", "Do not answer the user's message.", + } { + if !strings.Contains(request.Messages[0].Content, instruction) { + t.Errorf("title prompt missing style instruction %q", instruction) + } + } + if owner.Usage().PromptTokens != usage.PromptTokens || owner.Usage().PromptTokens != 10 || + replacement.Usage().PromptTokens != 0 { + t.Fatalf("usage moved to replacement: owner=%+v replacement=%+v", owner.Usage(), replacement.Usage()) + } + if client.MaxRetries != 7 { + t.Fatal("title changed the conversation retry policy") + } + }) + } +} + +func TestGenerateTitleInvalidOutputAndTransportAreSingleAttempt(t *testing.T) { + for _, test := range []struct { + name string + output string + status int + }{ + {name: "empty"}, + {name: "multiline", output: "First title\nSecond title"}, + {name: "too long", output: strings.Repeat("界", 81)}, + {name: "transient transport", status: http.StatusServiceUnavailable}, + } { + t.Run(test.name, func(t *testing.T) { + var requests atomic.Int32 + provider := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + request, ok := modelAccountingRequest(t, w, r) + if !ok { + return + } + requests.Add(1) + if test.status != 0 { + http.Error(w, "temporarily unavailable", test.status) + return + } + modelAccountingReply(w, request, test.output, modelAccountingUsage()) + })) + t.Cleanup(provider.Close) + client := llm.New(provider.URL, "test-key") + client.MaxRetries = 7 + runner := &AgentSession{agent: agent.NewRuntime(client, "model", 128, "", tools.NewServices())} + title, _, err := runner.GenerateTitle(t.Context(), "Name this request without history") + if err == nil || title != "" || requests.Load() != 1 { + t.Fatalf("title=%q error=%v requests=%d", title, err, requests.Load()) + } + if client.MaxRetries != 7 { + t.Fatal("title changed the conversation retry policy") + } + }) + } +} diff --git a/internal/daemon/title_notifications.go b/internal/daemon/title_notifications.go new file mode 100644 index 000000000..534196ef3 --- /dev/null +++ b/internal/daemon/title_notifications.go @@ -0,0 +1,61 @@ +package daemon + +import "github.com/context-labs/whip/internal/protocol" + +type titleListener struct { + notify func(string) +} + +// listenTitleChanges is owned by a protocol server, not by root subscriptions. +func (d *Daemon) listenTitleChanges(notify func(string)) func() { + listener := &titleListener{notify: notify} + d.titleMu.Lock() + if d.titleListeners == nil { + d.titleListeners = make(map[*titleListener]struct{}) + } + d.titleListeners[listener] = struct{}{} + d.titleMu.Unlock() + return func() { + d.titleMu.Lock() + delete(d.titleListeners, listener) + d.titleMu.Unlock() + } +} + +// Call only after the title commits and outside the root-registry lock. +func (d *Daemon) notifyTitleChanged(rootID string) { + d.titleMu.Lock() + listeners := make([]*titleListener, 0, len(d.titleListeners)) + for listener := range d.titleListeners { + listeners = append(listeners, listener) + } + d.titleMu.Unlock() + for _, listener := range listeners { + listener.notify(rootID) + } +} + +func (s *Session) notifyTitleChanged(rootID string) { + if s.titleChanged != nil { + s.titleChanged(rootID) + } +} + +func (s *Server) notifyTitleChanged(rootID string) { + if s.closed.Load() { + return + } + s.mu.Lock() + connections := make([]*serverConn, 0, len(s.clients)) + for connection := range s.clients { + // All initialized connections can read sessions.list; the transport + // owns local/network authorization. No root subscription is required. + if connection.titleNotifications { + connections = append(connections, connection) + } + } + s.mu.Unlock() + for _, connection := range connections { + connection.notify("sessions.title.changed", protocol.SessionTitleChangedParams{RootID: rootID}) + } +} diff --git a/internal/daemon/title_notifications_test.go b/internal/daemon/title_notifications_test.go new file mode 100644 index 000000000..95b3f8a2e --- /dev/null +++ b/internal/daemon/title_notifications_test.go @@ -0,0 +1,531 @@ +package daemon + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "net" + "os" + "path/filepath" + "slices" + "sync" + "testing" + "time" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +func titleNotificationServer(t *testing.T, options ServerOptions) (*Daemon, *Server) { + t.Helper() + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + server, err := NewServer(owner, options) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = server.Close() }) + return owner, server +} + +func readTitleMessage(t *testing.T, transport messageTransport) rpcMessage { + t.Helper() + _ = transport.SetReadDeadline(time.Now().Add(5 * time.Second)) + frame, err := transport.ReadMessage() + if err != nil { + t.Fatal(err) + } + message, err := decodeFrame(frame) + if err != nil { + t.Fatal(err) + } + return message +} + +func titlePing(t *testing.T, transport messageTransport) { + t.Helper() + if err := writeTransportMessage(transport, rpcMessage{ID: json.RawMessage("2"), Method: "daemon.ping", Params: json.RawMessage("{}")}); err != nil { + t.Fatal(err) + } + message := readTitleMessage(t, transport) + if string(message.ID) != "2" || message.Error != nil { + t.Fatalf("expected ping, not a notification: %+v", message) + } +} + +func connectTitleClient(t *testing.T, server *Server, id string, capabilities []string) messageTransport { + t.Helper() + // A short temporary directory keeps Unix socket paths below macOS's limit. + directory, err := os.MkdirTemp("", "whip-title-") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = os.RemoveAll(directory) }) + listener, err := net.Listen("unix", filepath.Join(directory, "socket")) + if err != nil { + t.Fatal(err) + } + defer listener.Close() + clientSide, err := net.Dial("unix", listener.Addr().String()) + if err != nil { + t.Fatal(err) + } + serverSide, err := listener.Accept() + if err != nil { + _ = clientSide.Close() + t.Fatal(err) + } + transport := newUnixMessageTransport(clientSide) + t.Cleanup(func() { _ = transport.Close() }) + if !server.goWorker(func() { server.serveConn(serverSide) }) { + t.Fatal("server closed") + } + params, _ := json.Marshal(InitializeParams{ + ProtocolMajor: ProtocolMajor, ClientID: id, ClientKind: "sdk", Capabilities: capabilities, + }) + if err := writeTransportMessage(transport, rpcMessage{ID: json.RawMessage("1"), Method: "initialize", Params: params}); err != nil { + t.Fatal(err) + } + message := readTitleMessage(t, transport) + var result InitializeResult + raw, _ := json.Marshal(message.Result) + if err := json.Unmarshal(raw, &result); err != nil || message.Error != nil { + t.Fatalf("initialize: %+v %v", message, err) + } + want := slices.Contains(capabilities, protocol.SessionTitleNotificationsCapability) + if !slices.Contains(result.Capabilities, protocol.SessionTitleNotificationsCapability) || + slices.Contains(result.NegotiatedCapabilities, protocol.SessionTitleNotificationsCapability) != want { + t.Fatalf("capability negotiation: %+v", result) + } + // This barrier also proves eligibility is set before any normal request runs. + titlePing(t, transport) + return transport +} + +func assertTitleMessage(t *testing.T, transport messageTransport, rootID string) { + t.Helper() + message := readTitleMessage(t, transport) + var params map[string]string + if err := json.Unmarshal(message.Params, ¶ms); err != nil || message.Method != "sessions.title.changed" || + len(message.ID) != 0 || len(params) != 1 || params["root_id"] != rootID { + t.Fatalf("title invalidation: %+v %v", message, err) + } +} + +func TestTitleNotificationsReachCatalogClientsWithoutSubscriptions(t *testing.T) { + owner, server := titleNotificationServer(t, ServerOptions{}) + capabilities := []string{protocol.SessionTitleNotificationsCapability} + first := connectTitleClient(t, server, "first", capabilities) + second := connectTitleClient(t, server, "second", append(capabilities, protocol.NetworkClientCapability)) + legacy := connectTitleClient(t, server, "legacy", nil) + rootID := createRoot(t, owner.store) + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + if result := clientCommand(t, root, "first", "rename", "session.rename", protocol.TitleParams{Title: "Private title"}); result.Status != "succeeded" { + t.Fatalf("rename: %+v", result) + } + assertTitleMessage(t, first, rootID) + assertTitleMessage(t, second, rootID) + for _, transport := range []messageTransport{first, second} { + params, _ := json.Marshal(protocol.RootParams{RootID: rootID}) + if err := writeTransportMessage(transport, rpcMessage{ID: json.RawMessage("3"), Method: "sessions.get", Params: params}); err != nil { + t.Fatal(err) + } + message := readTitleMessage(t, transport) + var metadata session.SessionMetadata + raw, _ := json.Marshal(message.Result) + if err := json.Unmarshal(raw, &metadata); err != nil || message.Error != nil || metadata.Title != "Private title" { + t.Fatalf("notification read before commit: %+v %v", message, err) + } + } + titlePing(t, legacy) + server.mu.Lock() + defer server.mu.Unlock() + for connection := range server.clients { + if len(connection.subscriptions) != 0 { + t.Fatal("title delivery opened a root subscription") + } + } +} + +type titleInitializeTransport struct { + messageTransport + started chan struct{} + release chan struct{} + fail bool + once sync.Once +} + +func (t *titleInitializeTransport) WriteMessage(frame []byte) error { + failed := false + t.once.Do(func() { + close(t.started) + <-t.release + failed = t.fail + }) + if failed { + return errors.New("initialize write failed") + } + return t.messageTransport.WriteMessage(frame) +} + +func TestTitleNotificationsWaitForSuccessfulInitializeWrite(t *testing.T) { + for _, fail := range []bool{false, true} { + t.Run(map[bool]string{false: "blocked", true: "failed"}[fail], func(t *testing.T) { + owner, server := titleNotificationServer(t, ServerOptions{}) + serverSide, clientSide := net.Pipe() + transport := newUnixMessageTransport(clientSide) + t.Cleanup(func() { _ = transport.Close() }) + blocked := &titleInitializeTransport{ + messageTransport: newUnixMessageTransport(serverSide), + started: make(chan struct{}), release: make(chan struct{}), fail: fail, + } + served := make(chan struct{}) + server.goWorker(func() { defer close(served); server.serveTransport(blocked, false) }) + params, _ := json.Marshal(InitializeParams{ + ProtocolMajor: ProtocolMajor, ClientKind: "sdk", ClientID: "initializing", + Capabilities: []string{protocol.SessionTitleNotificationsCapability}, + }) + if err := writeTransportMessage(transport, rpcMessage{ID: json.RawMessage("1"), Method: "initialize", Params: params}); err != nil { + t.Fatal(err) + } + waitTitleLifecycle(t, blocked.started) + owner.notifyTitleChanged("before-initialize") + server.mu.Lock() + for connection := range server.clients { + if connection.titleNotifications || len(connection.out) != 0 { + t.Error("notification queued before initialize completed") + } + } + server.mu.Unlock() + close(blocked.release) + if fail { + waitTitleLifecycle(t, served) + server.mu.Lock() + defer server.mu.Unlock() + if len(server.clients) != 0 { + t.Fatal("failed initialize left a registered client") + } + return + } + if message := readTitleMessage(t, transport); string(message.ID) != "1" { + t.Fatalf("initialize response: %+v", message) + } + titlePing(t, transport) + owner.notifyTitleChanged("after-initialize") + assertTitleMessage(t, transport, "after-initialize") + }) + } +} + +func TestTitleNotificationsBoundSlowClientsAndUnregisterOnClose(t *testing.T) { + owner, server := titleNotificationServer(t, ServerOptions{MaxOutbound: 1}) + _ = connectTitleClient(t, server, "slow", []string{protocol.SessionTitleNotificationsCapability}) + server.mu.Lock() + var slow *serverConn + for connection := range server.clients { + slow = connection + } + server.mu.Unlock() + rootID := createRoot(t, owner.store) + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + // Force overflow from the root actor, not just an unrelated broadcaster. + // Saturate byte accounting so the socket buffer cannot hide overflow. + slow.mu.Lock() + slow.outBytes = server.options.MaxOutboundBytes + slow.mu.Unlock() + published := make(chan struct{}) + go func() { + defer close(published) + if err := root.routeControl(t.Context(), func(ctx context.Context) error { + if err := root.store.SetTitle(rootID, "Slow title"); err != nil { + return err + } + return root.publishTitle(ctx, "Slow title") + }); err != nil { + t.Error(err) + } + }() + waitTitleLifecycle(t, published) + waitTitleLifecycle(t, slow.done) + finished := make(chan struct{}) + go func() { + defer close(finished) + for range 1000 { + owner.notifyTitleChanged("shutdown-race") + } + }() + closed := make(chan struct{}) + go func() { defer close(closed); _ = server.Close() }() + waitTitleLifecycle(t, closed) + waitTitleLifecycle(t, finished) + owner.titleMu.Lock() + defer owner.titleMu.Unlock() + if len(owner.titleListeners) != 0 { + t.Fatal("server retained a title listener after close") + } +} + +// Verify committed data and the registry are available before every callback. +func observeTitleChanges(t *testing.T, owner *Daemon) <-chan string { + t.Helper() + changes := make(chan string, 32) + unsubscribe := owner.listenTitleChanges(func(rootID string) { + if !owner.mu.TryLock() { + t.Error("title notification holds root registry mutex") + } else { + owner.mu.Unlock() + } + if meta, err := owner.store.SessionMetadata(t.Context(), rootID); err != nil || meta.Title == "" { + t.Errorf("notification preceded title commit: %+v %v", meta, err) + } + changes <- rootID + }) + t.Cleanup(unsubscribe) + return changes +} + +func assertTitleChanges(t *testing.T, changes <-chan string, rootIDs ...string) { + t.Helper() + for _, rootID := range rootIDs { + select { + case got := <-changes: + if got != rootID { + t.Fatalf("title change = %q, want %q", got, rootID) + } + default: + t.Fatalf("missing title change for %q", rootID) + } + } + select { + case extra := <-changes: + t.Fatalf("unexpected title change: %q", extra) + default: + } +} + +func TestTitleNotificationsCommittedWritePaths(t *testing.T) { + for _, test := range []struct { + name, prompt string + generated bool + optOut bool + }{ + {name: "short", prompt: "Short"}, + {name: "definition opt-out", prompt: "A long prompt with automatic generation disabled", optOut: true}, + {name: "generated", prompt: "A long first prompt requiring a generated title", generated: true}, + } { + t.Run(test.name, func(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + runner := &lifecycleTitleRunner{fakeRunner: &fakeRunner{}, generate: func(context.Context, string) (string, llm.Usage, error) { + return "Generated title", llm.Usage{}, nil + }} + owner, root := openTitleLifecycle(t, store, rootID, runner) + if test.optOut { + if err := root.routeControl(t.Context(), func(context.Context) error { + root.definition.Surface.AutoTitle = false + return nil + }); err != nil { + t.Fatal(err) + } + } + changes := observeTitleChanges(t, owner) + assertTitleChanges(t, changes) // Ordinary empty creation/open never emits. + receipt, err := root.Submit(t.Context(), test.prompt) + if err != nil { + t.Fatal(err) + } + if result := waitReceipt(t, receipt); result.Err != nil { + t.Fatal(result.Err) + } + settleTitleLifecycle(t, root) + if test.generated { + assertTitleChanges(t, changes, rootID, rootID) + } else { + assertTitleChanges(t, changes, rootID) + } + for _, title := range []string{"Manual title", "Manual title"} { + result := clientCommand(t, root, "client", "rename-"+title, "session.rename", protocol.TitleParams{Title: title}) + if result.Status != "succeeded" { + t.Fatalf("rename: %+v", result) + } + } + assertTitleChanges(t, changes, rootID) // Command replay does not repeat the hint. + for _, title := range []string{"", "Custom fork"} { + result := clientCommand(t, root, "client", "fork-"+title, "session.fork", protocol.ForkParams{Title: title}) + var fork protocol.RootIDResult + if err := json.Unmarshal(result.Result, &fork); err != nil || result.Status != "succeeded" { + t.Fatalf("fork: %+v %v", result, err) + } + assertTitleChanges(t, changes, fork.RootID) + _ = clientCommand(t, root, "client", "fork-"+title, "session.fork", protocol.ForkParams{Title: title}) + assertTitleChanges(t, changes) + } + }) + } +} + +func TestTitleNotificationsGeneratedResultRequiresCommittedWrite(t *testing.T) { + for _, scenario := range []string{"generated", "stale", "deleted", "generation failure", "write failure", "event failure"} { + t.Run(scenario, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + if err := store.SetTitle(rootID, "Placeholder"); err != nil { + t.Fatal(err) + } + owner, root := openTitleLifecycle(t, store, rootID, &fakeRunner{}) + changes := observeTitleChanges(t, owner) + if scenario == "write failure" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions + BEGIN SELECT RAISE(ABORT,'title write failed'); END`) + } else if scenario == "event failure" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON events + WHEN NEW.kind='session.title.updated' BEGIN SELECT RAISE(ABORT,'title event failed'); END`) + } + if err := root.routeControl(t.Context(), func(context.Context) error { + work := &titleWork{cancel: func() {}, placeholder: "Placeholder", title: "Generated title"} + root.titleWork = work + switch scenario { + case "stale": + if err := store.SetTitle(rootID, "Manual title"); err != nil { + return err + } + case "deleted": + if err := store.DeleteSession(t.Context(), rootID); err != nil { + return err + } + case "generation failure": + work.err = errors.New("generation failed") + } + root.completeTitle(work) + return nil + }); err != nil { + t.Fatal(err) + } + if scenario == "generated" || scenario == "event failure" { + assertTitleChanges(t, changes, rootID) + assertTitleLifecycle(t, store, rootID, "Generated title") + } else { + assertTitleChanges(t, changes) + } + }) + } +} + +func TestTitleNotificationsLiveWriteAndEventFailures(t *testing.T) { + for _, operation := range []string{"initial", "session.rename", "session.fork"} { + for _, failure := range []string{"write", "event"} { + if operation == "session.fork" && failure == "event" { + continue // Fork creates a root without publishing session.title.updated. + } + t.Run(operation+"/"+failure, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + owner, root := openTitleLifecycle(t, store, rootID, &fakeRunner{}) + changes := observeTitleChanges(t, owner) + if failure == "event" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON events + WHEN NEW.kind='session.title.updated' BEGIN SELECT RAISE(ABORT,'title event failed'); END`) + } else if operation == "session.fork" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON sessions + BEGIN SELECT RAISE(ABORT,'fork failed'); END`) + } else { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions + BEGIN SELECT RAISE(ABORT,'title write failed'); END`) + } + if operation == "initial" { + receipt, err := root.Submit(t.Context(), "Short title") + if (err != nil) != (failure == "write") { + t.Fatalf("initial title error: %v", err) + } + if err == nil { + if completion := waitReceipt(t, receipt); completion.Err != nil { + t.Fatal(completion.Err) + } + } + } else { + result := clientCommand(t, root, "client", "failed-command", operation, protocol.TitleParams{Title: "Manual title"}) + if result.Status != "failed" { + t.Fatalf("expected failed command: %+v", result) + } + } + if failure == "event" { + assertTitleChanges(t, changes, rootID) + } else { + assertTitleChanges(t, changes) + } + }) + } + } +} + +func titleFailureDB(t *testing.T, path, statement string) { + t.Helper() + db, err := sql.Open("sqlite", path) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err := db.ExecContext(t.Context(), statement); err != nil { + t.Fatal(err) + } +} + +func TestTitleNotificationsColdRenameCommitAndFailure(t *testing.T) { + for _, failure := range []string{"none", "event", "write"} { + t.Run(failure, func(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + t.Error("cold rename reconstructed a root") + return Components{}, errors.New("unavailable workspace") + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + changes := observeTitleChanges(t, owner) + if failure == "event" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON events + WHEN NEW.kind='session.title.updated' BEGIN SELECT RAISE(ABORT,'title event failed'); END`) + } else if failure == "write" { + titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions + BEGIN SELECT RAISE(ABORT,'title write failed'); END`) + } + payload := json.RawMessage(`{"title":"Cold title"}`) + admission := session.CommandAdmission{ + ClientID: "cold", CommandID: "rename", RequestDigest: "rename", Payload: session.RuntimePayload{Data: payload}, + } + record, err := owner.control.SessionMetadataCommand(t.Context(), admission, "session.rename", payload, rootID) + if (err == nil) != (failure == "none") { + t.Fatalf("rename error: %v", err) + } + if (record.Status == "succeeded") != (failure == "none") { + t.Fatalf("command status: %+v", record) + } + if failure == "write" { + assertTitleChanges(t, changes) + } else { + assertTitleChanges(t, changes, rootID) + assertTitleLifecycle(t, store, rootID, "Cold title") + } + _, _ = owner.control.SessionMetadataCommand(t.Context(), admission, "session.rename", payload, rootID) + assertTitleChanges(t, changes) + }) + } +} diff --git a/internal/daemon/v2_sdk_agents_test.go b/internal/daemon/v2_sdk_agents_test.go index c8b496690..b4c1f7eb7 100644 --- a/internal/daemon/v2_sdk_agents_test.go +++ b/internal/daemon/v2_sdk_agents_test.go @@ -82,6 +82,7 @@ func sdkAgentsFactory(store *session.Store) (Factory, func()) { if err != nil { return Components{}, err } + definition.Surface.AutoTitle = false runtime, err := NewRecursiveRuntime(RecursiveRuntimeOptions{ Engine: meta.ExecutionEngine, Definition: definition, Agent: value, History: history, Limits: limits, Kernels: rlm.NewManager(limits.MaxWorkers), KernelCommand: recursiveKernelCommand, diff --git a/internal/protocol/registry.go b/internal/protocol/registry.go index aa33ad206..7fa7d30ff 100644 --- a/internal/protocol/registry.go +++ b/internal/protocol/registry.go @@ -43,6 +43,12 @@ type PingResult struct { Generation int64 `json:"generation,string"` BuildID string `json:"build_id"` } + +// SessionTitleChangedParams invalidates title metadata on this host, without a root subscription. +type SessionTitleChangedParams struct { + RootID string `json:"root_id"` +} + type EventNotification struct { Event ProtocolEvent `json:"event"` } @@ -209,6 +215,7 @@ func Lookup(name string) (Operation, bool) { func Events() map[string]reflect.Type { return map[string]reflect.Type{ "event": reflect.TypeFor[EventNotification](), + "sessions.title.changed": reflect.TypeFor[SessionTitleChangedParams](), "subscription.failed": reflect.TypeFor[SubscriptionFailure](), "browser.provider.revoked": reflect.TypeFor[BrowserProviderRevoked](), "browser.inventory": reflect.TypeFor[BrowserInventoryRequest](), diff --git a/internal/protocol/registry_test.go b/internal/protocol/registry_test.go index 9abc00015..c7b1b9e47 100644 --- a/internal/protocol/registry_test.go +++ b/internal/protocol/registry_test.go @@ -1,13 +1,31 @@ package protocol import ( + "encoding/json" "go/ast" "go/parser" "go/token" + "reflect" "strconv" "testing" ) +func TestSessionTitleChangedContract(t *testing.T) { + if got := Events()["sessions.title.changed"]; got != reflect.TypeFor[SessionTitleChangedParams]() { + t.Fatalf("title notification type = %v", got) + } + payload, err := json.Marshal(SessionTitleChangedParams{RootID: "root"}) + if err != nil || string(payload) != `{"root_id":"root"}` { + t.Fatalf("title notification payload = %s, %v", payload, err) + } +} + +func TestAutomaticTitlesNeedNoRuntimeOptIn(t *testing.T) { + if _, ok := LookupRuntime("session.autotitle"); ok { + t.Fatal("automatic titles must not expose a per-session opt-in command") + } +} + func TestEveryRuntimeHandlerHasAContract(t *testing.T) { source, err := parser.ParseFile(token.NewFileSet(), "../daemon/client_control.go", nil, 0) if err != nil { diff --git a/internal/protocol/runtime_registry.go b/internal/protocol/runtime_registry.go index 2af331bc4..1adb82d5d 100644 --- a/internal/protocol/runtime_registry.go +++ b/internal/protocol/runtime_registry.go @@ -40,7 +40,6 @@ var runtimeOperations = []Operation{ action[ArchiveParams, ArchiveResult]("session.archive", Command, "root-association", false), action[TitleParams, TitleResult]("session.rename", Command, "root-association", false), action[EmptyParams, ModelResult]("session.reload", Command, "root-idle", false), - action[EmptyParams, Empty]("session.autotitle", Command, "root-association", false), action[RunConfigureParams, Empty]("run.configure", Command, "root-idle", false), action[ClearHistoryParams, Empty]("history.clear", Command, "root-idle", false), action[RewindParams, RewindResult]("history.rewind", Command, "root-idle", false), diff --git a/internal/protocol/types.go b/internal/protocol/types.go index f465e6dce..cd517f973 100644 --- a/internal/protocol/types.go +++ b/internal/protocol/types.go @@ -13,6 +13,8 @@ import ( const ( Major = 6 Minor = 8 + + SessionTitleNotificationsCapability = "session_title_notifications" ) type ErrorData struct { diff --git a/internal/session/command.go b/internal/session/command.go index a6fa31daf..62b8f8a65 100644 --- a/internal/session/command.go +++ b/internal/session/command.go @@ -37,9 +37,10 @@ type CommandRecord struct { } type CommandAdmissionResult struct { - Command CommandRecord - EventSeq int64 - New bool + Command CommandRecord + EventSeq int64 + New bool + TitleInitialization *TitleInitialization } // AdmitCommand compares command identity and request digest and, for a new @@ -99,6 +100,7 @@ func (s *Store) AdmitCommand(ctx context.Context, admission CommandAdmission) (C } result.Command.IngressSeq = sequence.InboxSeq result.EventSeq = sequence.EventSeq + result.TitleInitialization = sequence.TitleInitialization } else if err := tx.QueryRowContext(ctx, `SELECT COALESCE(MAX(ingress_seq),0)+1 FROM commands WHERE scope='daemon'`).Scan(&result.Command.IngressSeq); err != nil { return CommandAdmissionResult{}, err } diff --git a/internal/session/inbox_queue.go b/internal/session/inbox_queue.go index 340d9eab1..578c93eda 100644 --- a/internal/session/inbox_queue.go +++ b/internal/session/inbox_queue.go @@ -70,6 +70,7 @@ func inboxPreviewJSON(item InboxEnqueue) []byte { preview.Attachments = append(preview.Attachments, file) } } + preview.Text = strings.TrimSpace(preview.Text) preview.Truncated = len(preview.Text) > 2048 || preview.AttachmentCount > len(preview.Attachments) preview.Text = boundedUTF8(preview.Text, 2048) body, _ := json.Marshal(preview) diff --git a/internal/session/input_lifecycle_test.go b/internal/session/input_lifecycle_test.go index 0240c244b..7bdb0feb9 100644 --- a/internal/session/input_lifecycle_test.go +++ b/internal/session/input_lifecycle_test.go @@ -14,9 +14,15 @@ import ( func inputTestCommand(t *testing.T, store *Store, rootID, agentID, id, kind string) CommandAdmissionResult { t.Helper() + payload := []byte(id) + if strings.HasSuffix(kind, ".parts") { + payload, _ = json.Marshal(struct { + Text string `json:"text"` + }{Text: id}) + } result, err := store.AdmitCommand(t.Context(), CommandAdmission{ ClientID: rootID, CommandID: id, Scope: CommandScopeRoot, RootID: rootID, - AgentID: agentID, Kind: kind, RequestDigest: id, Payload: RuntimePayload{Data: []byte(id)}, + AgentID: agentID, Kind: kind, RequestDigest: id, Payload: RuntimePayload{Data: payload}, }) if err != nil { t.Fatal(err) @@ -345,6 +351,8 @@ func TestRejectTurnInputSettlesInvalidSteerWithoutFailingTurn(t *testing.T) { t.Fatal(err) } steer := inputTestCommand(t, store, rootID, rootAgentID, "bad-steer", "steer.parts") + // Simulate malformed input retained by an older admission path. + exec(t, store, `UPDATE inbox SET payload_inline=? WHERE root_id=? AND seq=?`, []byte("bad-steer"), rootID, steer.Command.IngressSeq) if _, err := store.ClaimSteers(t.Context(), rootID, rootAgentID, turnID); err != nil { t.Fatal(err) } diff --git a/internal/session/metadata_test.go b/internal/session/metadata_test.go index 1b0a94c0a..e082a23f9 100644 --- a/internal/session/metadata_test.go +++ b/internal/session/metadata_test.go @@ -23,6 +23,15 @@ func TestSessionMetadataReadsExactBoundedFields(t *testing.T) { if err != nil || value.RootID != root || value.Title != title || value.CWD != cwd || value.HistoryRevision != 9007199254740993 || value.Archived { t.Fatalf("metadata %+v %v", value, err) } + for _, id := range []string{root, root[:4]} { + meta, err := store.LoadMeta(id) + if err != nil || meta.ID != root || meta.Title != title { + t.Fatalf("metadata-only prefix read: %+v %v", meta, err) + } + } + if _, _, err := store.Load(root); err == nil { + t.Fatal("full load should still validate corrupt transcript") + } for _, invalid := range []string{"", strings.Repeat("x", 257), "missing", root[:4]} { if _, err := store.SessionMetadata(t.Context(), invalid); err == nil { t.Fatalf("invalid root accepted: %q", invalid) diff --git a/internal/session/runtime.go b/internal/session/runtime.go index 4ffd68f58..787ad4755 100644 --- a/internal/session/runtime.go +++ b/internal/session/runtime.go @@ -134,8 +134,9 @@ type InboxEnqueue struct { } type InboxSequence struct { - InboxSeq int64 - EventSeq int64 + InboxSeq int64 + EventSeq int64 + TitleInitialization *TitleInitialization } type InboxItem struct { @@ -702,6 +703,16 @@ func (s *Store) commitRootTurn(ctx context.Context, commit RootTurnCommit, befor continue } messageSeq++ + if message.Role == "user" { + // Preserve input provenance so admission can distinguish a new + // attachment-only conversation from unlinked historical messages. + presentation := llm.TranscriptPresentation{Version: 1} + if message.Presentation != nil { + presentation = *message.Presentation + } + presentation.TurnID = turnID + message.Presentation = &presentation + } data, err := json.Marshal(message) if err != nil { return err @@ -719,9 +730,8 @@ func (s *Store) commitRootTurn(ctx context.Context, commit RootTurnCommit, befor return err } } - title := ProvisionalTitle(commit.Messages) - if _, err := tx.ExecContext(ctx, `UPDATE sessions SET updated_at=?,model=?,provider=?,title=CASE WHEN title='' THEN ? ELSE title END WHERE id=?`, - stamp, commit.Model, commit.Provider, title, commit.RootID); err != nil { + if _, err := tx.ExecContext(ctx, `UPDATE sessions SET updated_at=?,model=?,provider=? WHERE id=?`, + stamp, commit.Model, commit.Provider, commit.RootID); err != nil { return err } if status == "succeeded" { @@ -1121,6 +1131,11 @@ func (s *Store) enqueueInboxTx(ctx context.Context, tx *sql.Tx, item InboxEnqueu return InboxSequence{}, ErrRootTerminal } var sequence InboxSequence + title, err := initializeInputTitleTx(ctx, tx, item) + if err != nil { + return InboxSequence{}, err + } + sequence.TitleInitialization = title if err := tx.QueryRowContext(ctx, `SELECT COALESCE(MAX(seq),0)+1 FROM inbox WHERE root_id=? AND agent_id=?`, item.RootID, item.AgentID).Scan(&sequence.InboxSeq); err != nil { return InboxSequence{}, err } diff --git a/internal/session/session.go b/internal/session/session.go index 060502942..e9f7ae520 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -246,6 +246,8 @@ func (s *Store) Save(id string, from int, msgs []llm.Message, model, provider st return err } } + // Legacy bulk-history writers have no input admission boundary. The actor + // runtime initializes titles at admission instead of using this fallback. title := ProvisionalTitle(msgs) if _, err := tx.ExecContext(context.Background(), `UPDATE sessions SET updated_at=?, model=?, provider=?, title=CASE WHEN title='' THEN ? ELSE title END WHERE id=?`, now(), model, provider, title, id); err != nil { @@ -261,27 +263,35 @@ func (s *Store) Save(id string, from int, msgs []llm.Message, model, provider st // Load resolves idOrPrefix to a session and returns its metadata and messages. func (s *Store) Load(idOrPrefix string) (Meta, []llm.Message, error) { - rows, err := s.db.QueryContext(context.Background(), `SELECT id,kind,title,model,provider,cwd,goal,forked_from,fork_seq,tags,pinned,archived,effort,usage_in,usage_cached,usage_out,updated_at,execution_engine,definition,definition_revision FROM sessions WHERE id LIKE ?||'%' LIMIT 3`, idOrPrefix) + meta, err := s.LoadMeta(idOrPrefix) if err != nil { return Meta{}, nil, err } - metas, err := scanMetas(rows) + msgs, err := s.loadMessages(meta.ID) if err != nil { return Meta{}, nil, err } + return meta, msgs, nil +} + +// LoadMeta resolves a session ID or unique prefix without reading its transcript. +func (s *Store) LoadMeta(idOrPrefix string) (Meta, error) { + rows, err := s.db.QueryContext(context.Background(), `SELECT id,kind,title,model,provider,cwd,goal,forked_from,fork_seq,tags,pinned,archived,effort,usage_in,usage_cached,usage_out,updated_at,execution_engine,definition,definition_revision FROM sessions WHERE id LIKE ?||'%' LIMIT 3`, idOrPrefix) + if err != nil { + return Meta{}, err + } + metas, err := scanMetas(rows) + if err != nil { + return Meta{}, err + } switch len(metas) { case 0: - return Meta{}, nil, fmt.Errorf("no session matching %q", idOrPrefix) + return Meta{}, fmt.Errorf("no session matching %q", idOrPrefix) case 1: default: - return Meta{}, nil, fmt.Errorf("session id %q is ambiguous", idOrPrefix) - } - meta := metas[0] - msgs, err := s.loadMessages(meta.ID) - if err != nil { - return Meta{}, nil, err + return Meta{}, fmt.Errorf("session id %q is ambiguous", idOrPrefix) } - return meta, msgs, nil + return metas[0], nil } // loadMessages reads one root session's full message log by exact id after @@ -922,9 +932,11 @@ func (s *Store) SetTitle(id, title string) error { return err } -// SetTitleIf preserves an explicit /rename that races automatic title work. -func (s *Store) SetTitleIf(id, current, title string) (bool, error) { - result, err := s.db.ExecContext(context.Background(), `UPDATE sessions SET title=? WHERE id=? AND title=?`, title, id, current) +// SetTitleIfContext conditionally retitles a session with the caller's persistence +// deadline. The caller must separately invalidate work on an explicit rename, +// including a rename back to the same text. Deleted sessions are a no-op. +func (s *Store) SetTitleIfContext(ctx context.Context, id, current, title string) (bool, error) { + result, err := s.db.ExecContext(ctx, `UPDATE sessions SET title=? WHERE id=? AND title=?`, title, id, current) if err != nil { return false, err } diff --git a/internal/session/title.go b/internal/session/title.go index 7d1de949a..5290ff55f 100644 --- a/internal/session/title.go +++ b/internal/session/title.go @@ -1,13 +1,34 @@ package session import ( + "context" + "database/sql" + "encoding/json" + "fmt" "strings" + "unicode/utf8" "github.com/context-labs/whip/internal/llm" ) const provisionalTitleRunes = 64 +// TitleInitialization is returned only by the admission that committed the +// initial title. Prompt contains authored text, never expanded attachments. +type TitleInitialization struct { + Title string + Prompt string +} + +func provisionalTitleText(text string) string { + title := strings.Join(strings.Fields(text), " ") + runes := []rune(title) + if len(runes) > provisionalTitleRunes { + return string(runes[:provisionalTitleRunes-1]) + "…" + } + return title +} + // ProvisionalTitle derives the initial session title from the first message the // user authored. The returned title is whitespace-normalized and at most 64 // runes, including the ellipsis. @@ -16,12 +37,109 @@ func ProvisionalTitle(messages []llm.Message) string { if message.Role != "user" || !message.Authored { continue } - title := strings.Join(strings.Fields(message.TextContent()), " ") - runes := []rune(title) - if len(runes) > provisionalTitleRunes { - return string(runes[:provisionalTitleRunes-1]) + "…" - } - return title + return provisionalTitleText(message.TextContent()) } return "" } + +// authoredInputText reads only the submitted text fields. Attachment references, +// image data, and design context are deliberately not naming context. +func authoredInputText(item InboxEnqueue) (string, error) { + if item.Kind != "submit.parts" && item.Kind != "steer.parts" { + return string(item.Payload.Data), nil + } + var body struct { + Text string `json:"text"` + Parts []llm.ContentPart `json:"parts"` + } + if err := json.Unmarshal(item.Payload.Data, &body); err != nil { + return "", fmt.Errorf("%w: invalid content-parts submission: %w", ErrInvalidInput, err) + } + text := []string{body.Text} + for _, part := range body.Parts { + if part.Type == "text" { + text = append(text, part.Text) + } + } + return strings.TrimSpace(strings.Join(text, "\n")), nil +} + +func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) (*TitleInitialization, error) { + if item.RootID != item.AgentID || item.Origin != "client" || clientInputOrigin(item.Kind) == "" { + return nil, nil + } + prompt, err := authoredInputText(item) + if err != nil { + return nil, err + } + title := provisionalTitleText(prompt) + if title == "" { + return nil, nil + } + var current, forkedFrom string + var revision int64 + if err := tx.QueryRowContext(ctx, `SELECT title,forked_from,history_revision + FROM sessions WHERE id=?`, item.RootID).Scan(¤t, &forkedFrom, &revision); err != nil { + return nil, err + } + if current != "" || forkedFrom != "" || revision != 0 { + return nil, nil + } + var firstTurn sql.NullString + if err := tx.QueryRowContext(ctx, `SELECT + (SELECT CASE WHEN json_valid(content) THEN COALESCE(json_extract(content,'$.presentation.turn_id'),'') ELSE '' END + FROM messages WHERE session_id=? ORDER BY seq LIMIT 1)`, item.RootID).Scan(&firstTurn); err != nil { + return nil, err + } + if firstTurn.Valid && firstTurn.String == "" { + return nil, nil + } + // Retained inbox metadata proves that previous human input had no usable + // text. Unknown legacy previews are not evidence of an attachment-only start. + rows, err := tx.QueryContext(ctx, `SELECT seq,origin,preview FROM inbox + WHERE root_id=? AND agent_id=? AND kind IN ('submit','submit.parts','steer','steer.parts') + AND origin<>'internal' ORDER BY seq`, item.RootID, item.AgentID) + if err != nil { + return nil, err + } + defer func() { _ = rows.Close() }() + historyLinked := !firstTurn.Valid + for rows.Next() { + var seq int64 + var origin string + var data []byte + if err := rows.Scan(&seq, &origin, &data); err != nil { + return nil, err + } + preview := readInboxPreview(data) + // A legacy preview truncated in whitespace may hide text after its + // 2048-byte boundary; the UTF-8 truncator can drop up to three bytes. + if origin != "client" || preview == nil || strings.TrimSpace(preview.Text) != "" || + preview.Truncated && len(preview.Text) >= 2048-utf8.UTFMax+1 { + return nil, nil + } + if firstTurn.String == rootTurnID(item.AgentID, seq) { + historyLinked = true + } + } + if err := rows.Err(); err != nil { + return nil, err + } + if err := rows.Close(); err != nil { + return nil, err + } + // A history without a known no-text admission is historical, not a new + // conversation. Reading only its first row also avoids expanded file text. + if !historyLinked { + return nil, nil + } + result, err := tx.ExecContext(ctx, `UPDATE sessions SET title=? WHERE id=? AND title=''`, title, item.RootID) + if err != nil { + return nil, err + } + changed, err := result.RowsAffected() + if err != nil || changed == 0 { + return nil, err + } + return &TitleInitialization{Title: title, Prompt: prompt}, nil +} diff --git a/internal/session/title_admission_test.go b/internal/session/title_admission_test.go new file mode 100644 index 000000000..3478e1ec3 --- /dev/null +++ b/internal/session/title_admission_test.go @@ -0,0 +1,340 @@ +package session + +import ( + "context" + "errors" + "fmt" + "path/filepath" + "strings" + "sync" + "testing" + + "github.com/context-labs/whip/internal/llm" +) + +func titleAdmission(root, agent, id, kind, payload string) CommandAdmission { + return CommandAdmission{ + ClientID: "title-test", CommandID: id, Scope: CommandScopeRoot, + RootID: root, AgentID: agent, Kind: kind, RequestDigest: id, + Payload: RuntimePayload{Data: []byte(payload)}, + } +} + +func assertStoredTitle(t *testing.T, store *Store, root, want string) { + t.Helper() + var title string + if err := store.db.QueryRowContext(t.Context(), "SELECT title FROM sessions WHERE id=?", root).Scan(&title); err != nil { + t.Fatal(err) + } + if title != want { + t.Fatalf("title = %q, want %q", title, want) + } +} + +func TestTitleInitializedAtAdmission(t *testing.T) { + for _, test := range []struct { + name, kind, payload, prompt, title string + }{ + {"text", "submit", " Fix\n the bug ", " Fix\n the bug ", "Fix the bug"}, + {"unicode", "steer", strings.Repeat("界", 65), strings.Repeat("界", 65), strings.Repeat("界", 63) + "…"}, + {"multipart", "submit.parts", `{"text":"Fix","parts":[{"type":"text","text":"the bug"},{"type":"image_url","image_url":{"url":"ignored"}}],"attachments":[{"kind":"text","name":"ignored.txt"}]}`, "Fix\nthe bug", "Fix the bug"}, + {"parts only", "steer.parts", `{"parts":[{"type":"text","text":"First"},{"type":"text","text":"second"}]}`, "First\nsecond", "First second"}, + } { + t.Run(test.name, func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + before, err := store.SessionCatalogRevision(t.Context()) + if err != nil { + t.Fatal(err) + } + admission := titleAdmission(root, agent, "first", test.kind, test.payload) + result, err := store.AdmitCommand(t.Context(), admission) + if err != nil { + t.Fatal(err) + } + if result.TitleInitialization == nil || *result.TitleInitialization != (TitleInitialization{Title: test.title, Prompt: test.prompt}) { + t.Fatalf("initialization = %+v", result.TitleInitialization) + } + assertStoredTitle(t, store, root, test.title) + after, err := store.SessionCatalogRevision(t.Context()) + if err != nil || before == after { + t.Fatalf("catalog revision did not change: %v", err) + } + replay, err := store.AdmitCommand(t.Context(), admission) + if err != nil || replay.New || replay.TitleInitialization != nil { + t.Fatalf("replay = %+v, %v", replay, err) + } + if err := store.SetTitle(root, ""); err != nil { + t.Fatal(err) + } + later, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, "later", "submit", "different")) + if err != nil || later.TitleInitialization != nil { + t.Fatalf("later = %+v, %v", later, err) + } + assertStoredTitle(t, store, root, "") + }) + } +} + +func TestTitleAttachmentOnlyWaitsAcrossTurnAndRestart(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store, err := Open(path) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = store.Close() }) + root, err := store.Create(SessionKindAgent, t.TempDir(), "model", "provider") + if err != nil { + t.Fatal(err) + } + if _, err := store.EnsureAuthority(t.Context(), root); err != nil { + t.Fatal(err) + } + first, err := store.AdmitCommand(t.Context(), titleAdmission(root, root, "attachment", "submit.parts", `{"text":" ","attachments":[{"kind":"text","name":"notes.txt"}]}`)) + if err != nil || first.TitleInitialization != nil { + t.Fatalf("attachment = %+v, %v", first, err) + } + assertStoredTitle(t, store, root, "") + if err := store.StartRootTurn(t.Context(), root, root, first.Command.IngressSeq); err != nil { + t.Fatal(err) + } + if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ + RootID: root, AgentID: root, InboxSeq: first.Command.IngressSeq, Model: "model", Provider: "provider", + Messages: []llm.Message{{Role: "user", Content: "expanded attachment text", Authored: true}, {Role: "assistant", Content: "done"}}, + }); err != nil { + t.Fatal(err) + } + assertStoredTitle(t, store, root, "") + if err := store.Close(); err != nil { + t.Fatal(err) + } + store, err = Open(path) + if err != nil { + t.Fatal(err) + } + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, root, "text", "submit", "User question")) + if err != nil || result.TitleInitialization == nil { + t.Fatalf("text = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, "User question") + if err := store.SetTitle(root, ""); err != nil { + t.Fatal(err) + } + if err := store.Close(); err != nil { + t.Fatal(err) + } + store, err = Open(path) + if err != nil { + t.Fatal(err) + } + result, err = store.AdmitCommand(t.Context(), titleAdmission(root, root, "restart", "submit", "Do not backfill")) + if err != nil || result.TitleInitialization != nil { + t.Fatalf("restart = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, "") +} + +func TestTitleAdmissionPreservesExistingAndHistoricalRoots(t *testing.T) { + for _, test := range []string{"manual", "fork", "history", "history then attachment", "malformed history", "legacy inbox", "rewound", "previous truncated text"} { + t.Run(test, func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + want := "" + switch test { + case "manual": + want = "My name" + if err := store.SetTitle(root, want); err != nil { + t.Fatal(err) + } + case "fork": + exec(t, store, "UPDATE sessions SET forked_from='parent' WHERE id=?", root) + case "malformed history": + exec(t, store, "INSERT INTO messages(session_id,seq,role,content) VALUES(?,1,'user','malformed')", root) + case "rewound": + exec(t, store, "UPDATE sessions SET history_revision=1 WHERE id=?", root) + case "history", "history then attachment": + if err := store.Save(root, 0, []llm.Message{{Role: "user", Content: "old authored text", Authored: true}}, "model", "provider"); err != nil { + t.Fatal(err) + } + if err := store.SetTitle(root, ""); err != nil { + t.Fatal(err) + } + if test == "history then attachment" { + if _, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, "attachment", "submit.parts", `{"attachments":[{"kind":"text","name":"notes"}]}`)); err != nil { + t.Fatal(err) + } + } + case "legacy inbox", "previous truncated text": + item, err := store.EnqueueInbox(t.Context(), InboxEnqueue{RootID: root, AgentID: agent, Kind: "submit", Payload: RuntimePayload{Data: []byte("old")}}) + if err != nil { + t.Fatal(err) + } + if test == "previous truncated text" { + exec(t, store, "UPDATE inbox SET origin='client',preview=? WHERE root_id=? AND seq=?", `{"text":"`+strings.Repeat(" ", 2048)+`","truncated":true}`, root, item.InboxSeq) + } + } + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, "new", "submit", "New text")) + if err != nil || result.TitleInitialization != nil { + t.Fatalf("result = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, want) + }) + } +} + +func TestTitleOnlyNamesClientRootInput(t *testing.T) { + for _, test := range []struct { + kind, origin string + child bool + }{ + {"submit", "client", true}, {"steer", "internal", false}, {"submit", "", false}, {"goal", "client", false}, {"mailbox", "client", false}, + } { + t.Run(fmt.Sprintf("%s-%s-%t", test.kind, test.origin, test.child), func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + if test.child { + admitTestChild(t, store, root, agent, "child") + agent = "child" + } + result, err := store.EnqueueInbox(t.Context(), InboxEnqueue{RootID: root, AgentID: agent, Kind: test.kind, Origin: test.origin, Payload: RuntimePayload{Data: []byte("not user text")}}) + if err != nil || result.TitleInitialization != nil { + t.Fatalf("result = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, "") + }) + } + store, root, agent := newSwarmFixture(t) + result, err := store.EnqueueInbox(t.Context(), InboxEnqueue{RootID: root, AgentID: agent, Kind: "submit", Origin: "client", Payload: RuntimePayload{Data: []byte("legacy client")}}) + if err != nil || result.TitleInitialization == nil { + t.Fatalf("legacy result = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, "legacy client") +} + +func TestTitleAdmissionRollback(t *testing.T) { + for _, test := range []string{"invalid parts", "cancelled", "title write", "inbox write", "event write", "command write"} { + t.Run(test, func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + ctx := t.Context() + admission := titleAdmission(root, agent, "first", "submit", "Do not title") + switch test { + case "invalid parts": + admission.Kind = "submit.parts" + admission.Payload.Data = []byte("invalid") + case "cancelled": + var cancel context.CancelFunc + ctx, cancel = context.WithCancel(ctx) + cancel() + case "title write": + exec(t, store, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions BEGIN SELECT RAISE(ABORT,'title failure'); END`) + default: + table := map[string]string{"inbox write": "inbox", "event write": "events", "command write": "commands"}[test] + exec(t, store, "CREATE TRIGGER fail_title_test BEFORE INSERT ON "+table+" BEGIN SELECT RAISE(ABORT,'input failure'); END") + } + result, err := store.AdmitCommand(ctx, admission) + if err == nil || result.TitleInitialization != nil { + t.Fatalf("result = %+v, %v", result, err) + } + assertStoredTitle(t, store, root, "") + for _, table := range []string{"inbox", "commands"} { + var count int + if err := store.db.QueryRowContext(t.Context(), "SELECT COUNT(*) FROM "+table).Scan(&count); err != nil || count != 0 { + t.Fatalf("%s rows = %d, %v", table, count, err) + } + } + }) + } +} + +func TestConcurrentInputsInitializeOneTitle(t *testing.T) { + store, root, agent := newSwarmFixture(t) + const callers = 12 + results := make(chan *TitleInitialization, callers) + errs := make(chan error, callers) + var wg sync.WaitGroup + for i := range callers { + wg.Go(func() { + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, fmt.Sprint(i), "submit", fmt.Sprintf("Prompt %d", i))) + results <- result.TitleInitialization + errs <- err + }) + } + wg.Wait() + close(results) + close(errs) + for err := range errs { + if err != nil { + t.Fatal(err) + } + } + var initialized []*TitleInitialization + for result := range results { + if result != nil { + initialized = append(initialized, result) + } + } + if len(initialized) != 1 { + t.Fatalf("initializations = %d", len(initialized)) + } + assertStoredTitle(t, store, root, initialized[0].Title) +} + +func TestTitleWaitsForQueuedTextAndSurvivesTurnFailure(t *testing.T) { + for _, status := range []string{"succeeded", "failed", "cancelled"} { + t.Run(status, func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + for i, payload := range []string{"", "\t\n\u2003", strings.Repeat(" ", 3000)} { + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, fmt.Sprint(i), "submit", payload)) + if err != nil || result.TitleInitialization != nil { + t.Fatalf("empty admission = %+v, %v", result, err) + } + } + first, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, "text", "submit", "Actual text")) + if err != nil || first.TitleInitialization == nil { + t.Fatalf("text = %+v, %v", first, err) + } + if err := store.StartRootTurn(t.Context(), root, agent, first.Command.IngressSeq); err != nil { + t.Fatal(err) + } + if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ + RootID: root, AgentID: agent, InboxSeq: first.Command.IngressSeq, Status: status, Model: "model", Provider: "provider", + Messages: []llm.Message{{Role: "user", Content: "expanded text", Authored: true}}, + }); err != nil { + t.Fatal(err) + } + assertStoredTitle(t, store, root, "Actual text") + }) + } +} + +func TestLegacyTitleAdmissionRollsBackAfterTitleWrite(t *testing.T) { + store, root, agent := newSwarmFixture(t) + exec(t, store, `CREATE TRIGGER fail_legacy_inbox BEFORE INSERT ON inbox BEGIN SELECT RAISE(ABORT,'input failure'); END`) + result, err := store.EnqueueInbox(t.Context(), InboxEnqueue{RootID: root, AgentID: agent, Origin: "client", Kind: "submit", Payload: RuntimePayload{Data: []byte("No title")}}) + if err == nil || result.TitleInitialization != nil { + t.Fatalf("result = %+v,%v", result, err) + } + assertStoredTitle(t, store, root, "") +} + +func TestSetTitleIfContext(t *testing.T) { + store, root, _ := newSwarmFixture(t) + if err := store.SetTitle(root, "Fallback"); err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithCancel(t.Context()) + cancel() + if changed, err := store.SetTitleIfContext(ctx, root, "Fallback", "Generated"); changed || !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled = %t,%v", changed, err) + } + assertStoredTitle(t, store, root, "Fallback") + if changed, err := store.SetTitleIfContext(t.Context(), root, "Stale", "Generated"); changed || err != nil { + t.Fatalf("stale = %t,%v", changed, err) + } + if changed, err := store.SetTitleIfContext(t.Context(), root, "Fallback", "Generated"); !changed || err != nil { + t.Fatalf("write = %t,%v", changed, err) + } + if err := store.DeleteSession(t.Context(), root); err != nil { + t.Fatal(err) + } + if changed, err := store.SetTitleIfContext(t.Context(), root, "Generated", "Late"); changed || err != nil { + t.Fatalf("deleted = %t,%v", changed, err) + } +} diff --git a/internal/session/title_test.go b/internal/session/title_test.go index 9ecbe8f95..336fb6b37 100644 --- a/internal/session/title_test.go +++ b/internal/session/title_test.go @@ -90,8 +90,8 @@ func TestProvisionalTitlePersistsAcrossWritePaths(t *testing.T) { t.Fatal(err) } meta, _, err := store.Load(rootID) - if err != nil || meta.Title != want || !utf8.ValidString(meta.Title) { - t.Fatalf("persisted title = %q, err = %v", meta.Title, err) + if err != nil || meta.Title != "" { + t.Fatalf("turn completion initialized title = %q, err = %v", meta.Title, err) } }) } diff --git a/internal/session/transcript_test.go b/internal/session/transcript_test.go index 7047312c7..e0459a74b 100644 --- a/internal/session/transcript_test.go +++ b/internal/session/transcript_test.go @@ -112,6 +112,17 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( } cursor = page.NextSeq } + if !child { + for i := range restoredRaw { + if restoredRaw[i].Role == "user" { + wantTurn := map[int]int64{0: 1, 4: 2, 6: 3}[i] + if restoredRaw[i].Presentation == nil || restoredRaw[i].Presentation.TurnID != rootTurnID(agentID, wantTurn) { + t.Fatal("root input lost its turn provenance") + } + restoredRaw[i].Presentation = raw[i].Presentation + } + } + } want, _ := json.Marshal(raw) got, _ := json.Marshal(restoredRaw) if string(got) != string(want) { diff --git a/internal/tui/client.go b/internal/tui/client.go index b7a55df97..876c3ac33 100644 --- a/internal/tui/client.go +++ b/internal/tui/client.go @@ -216,17 +216,6 @@ func configureInteractiveSession(ctx context.Context, client *Client, cautious, return err } } - action, err := client.NewAction("session.autotitle", protocol.EmptyParams{}) - if err != nil { - return fmt.Errorf("configure automatic titles: %w", err) - } - result, err := client.Command(ctx, action) - if err != nil { - return fmt.Errorf("configure automatic titles: %w", err) - } - if result.Status != "succeeded" { - return fmt.Errorf("configure automatic titles: %s", result.Error) - } return nil } diff --git a/internal/tui/client_test.go b/internal/tui/client_test.go index 12ad08b4c..b4d8f089f 100644 --- a/internal/tui/client_test.go +++ b/internal/tui/client_test.go @@ -100,7 +100,7 @@ func waitClientState(t *testing.T, client *Client, want ClientState) []ClientSta } } -func TestInteractiveSetupAppliesCautiousModeBeforeAutomaticTitles(t *testing.T) { +func TestInteractiveSetupAppliesCautiousMode(t *testing.T) { connection := newFakeDaemonConnection(session.RootSnapshot{RootID: "root"}) client, err := NewClient(ClientOptions{ ClientID: "tui", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, @@ -116,7 +116,7 @@ func TestInteractiveSetupAppliesCautiousModeBeforeAutomaticTitles(t *testing.T) } connection.mu.Lock() defer connection.mu.Unlock() - if len(connection.commands) != 2 || connection.commands[0].Operation != "permission.mode" || connection.commands[1].Operation != "session.autotitle" { + if len(connection.commands) != 1 || connection.commands[0].Operation != "permission.mode" { t.Fatalf("interactive setup command order=%+v", connection.commands) } } @@ -138,7 +138,7 @@ func TestInteractiveSetupAppliesYoloModeOnlyToInitialSession(t *testing.T) { connection.mu.Lock() commands := append([]daemon.CommandParams(nil), connection.commands...) connection.mu.Unlock() - if len(commands) != 2 || commands[0].Operation != "permission.mode" || !strings.Contains(string(commands[0].Payload), `"external_permissions":false`) || commands[1].Operation != "session.autotitle" { + if len(commands) != 1 || commands[0].Operation != "permission.mode" || !strings.Contains(string(commands[0].Payload), `"external_permissions":false`) { t.Fatalf("yolo setup commands=%+v", commands) } @@ -160,7 +160,7 @@ func TestInteractiveSetupAppliesYoloModeOnlyToInitialSession(t *testing.T) { } connection.mu.Lock() defer connection.mu.Unlock() - if len(connection.commands) != 2 { + if len(connection.commands) != 1 { t.Fatalf("attaching changed saved permissions: %+v", connection.commands) } } @@ -181,7 +181,7 @@ func TestInteractiveSetupWithoutFlagsPreservesSavedPermissions(t *testing.T) { } connection.mu.Lock() defer connection.mu.Unlock() - if len(connection.commands) != 1 || connection.commands[0].Operation != "session.autotitle" { + if len(connection.commands) != 0 { t.Fatalf("setup replaced saved permissions: %+v", connection.commands) } } diff --git a/internal/tui/startup_test.go b/internal/tui/startup_test.go index 8179dbf10..21305026e 100644 --- a/internal/tui/startup_test.go +++ b/internal/tui/startup_test.go @@ -151,15 +151,15 @@ func TestOnboardingStaysInNormalTUIUntilExplicitFirstSend(t *testing.T) { } var selected daemon.CreateSession var selectedEffort protocol.EffortParams - if len(connection.commands) == 4 { + if len(connection.commands) == 3 { _ = json.Unmarshal(connection.commands[0].Payload, &selected) - _ = json.Unmarshal(connection.commands[3].Payload, &selectedEffort) + _ = json.Unmarshal(connection.commands[2].Payload, &selectedEffort) } connection.mu.Unlock() if selected.Model != "z-ai/glm-5.3" || selected.Provider != "openrouter" || selectedEffort.Effort != "max" { t.Fatalf("first session lost selection: %+v %+v", selected, selectedEffort) } - if strings.Join(operations, ",") != "session.create,permission.mode,session.autotitle,session.effort" { + if strings.Join(operations, ",") != "session.create,permission.mode,session.effort" { t.Fatalf("unexpected preparation/submission order: %v", operations) } _, cmd = m.Update(setupKey("enter")) diff --git a/packages/app/src/details/session-controls.tsx b/packages/app/src/details/session-controls.tsx index 8243f30d3..be43aa1bb 100644 --- a/packages/app/src/details/session-controls.tsx +++ b/packages/app/src/details/session-controls.tsx @@ -315,22 +315,6 @@ function Context(props: InspectorProps) { Change workspace -
- - runtime.run( - props.view.session.command('session.autotitle', {}), - 'Enable automatic titles', - ) - } - > - Enable automatic titles - -
); } diff --git a/packages/app/src/runtime.ts b/packages/app/src/runtime.ts index 0395ec0d6..11df9b1f7 100644 --- a/packages/app/src/runtime.ts +++ b/packages/app/src/runtime.ts @@ -112,6 +112,7 @@ export class AppRuntime { private state: RuntimeSnapshot; private readonly listeners = new Set<() => void>(); private readonly views = new Map(); + private readonly titleListeners = new Map void>(); private readonly drafts = new Map(); private readonly draftRevisions = new Map(); private readonly draftListeners = new Map void>>(); @@ -204,6 +205,7 @@ export class AppRuntime { } catch (error) { this.report(error); } this.connections = new HostConnections(platform, this.recoveryStorage(), { connected: (runtimeId, client) => { + this.observeSessionTitles(runtimeId, client); void this.queries.invalidateQueries({ predicate: query => query.queryKey[1] === runtimeId }); void this.primeProviders(runtimeId, client); void this.queries.prefetchQuery({ queryKey: ['runtime-configuration', runtimeId], @@ -218,6 +220,8 @@ export class AppRuntime { }); }, detached: (client, runtimeId) => { + this.titleListeners.get(client)?.(); + this.titleListeners.delete(client); if (runtimeId) this.compositions.invalidateRuntime(runtimeId); for (const [id, pending] of this.pending) if (pending.client === client) this.pending.delete(id); for (const [id, lease] of this.views) if (lease.client === client) this.dropView(id, lease); @@ -288,6 +292,29 @@ export class AppRuntime { ) return { runtimeId: saved.runtimeId, rootId: saved.rootId }; } + private observeSessionTitles(runtimeId: string, client: WhipClient) { + this.titleListeners.get(client)?.(); + this.titleListeners.delete(client); + if (!client.getSnapshot().info?.negotiated_capabilities?.includes('session_title_notifications')) return; + let retired = false; + let timer: ReturnType | undefined; + const attached = () => !retired && !this.closed && this.connections.isAttached(client) + && client.getSnapshot().state === 'connected'; + const filters = { predicate: (query: { queryKey: readonly unknown[] }) => query.queryKey[1] === runtimeId + && ['session-tab-summaries', 'session-sidebar-summaries', 'session-search', 'host-attention'].includes(query.queryKey[0] as string) }; + const off = client.onNotification('sessions.title.changed', () => { + if (!attached() || timer) return; + timer = setTimeout(() => { + timer = undefined; + if (!attached()) return; + // Explicit cancellation also covers first loads (invalidate alone can reuse their stale result). + void this.queries.cancelQueries(filters).then(() => { + if (attached()) return this.queries.invalidateQueries(filters); + }); + }, 250); + }); + this.titleListeners.set(client, () => { retired = true; clearTimeout(timer); off(); }); + } /** Warm provider readiness using the verified client, even before its host snapshot is published. */ primeProviders(runtimeId?: string, client = runtimeId ? this.connections.host(runtimeId)?.client : undefined): Promise { if (!runtimeId || !client) return Promise.resolve(); diff --git a/packages/app/src/session-actions.tsx b/packages/app/src/session-actions.tsx index de2cd3053..3b6243290 100644 --- a/packages/app/src/session-actions.tsx +++ b/packages/app/src/session-actions.tsx @@ -17,7 +17,7 @@ export interface SessionActionTarget { type Action = 'rename' | 'fork' | 'delete' | 'ssh'; type Metadata = Awaited>; interface Selection { target: SessionActionTarget; hostName: string; client: WhipClient; action: Action; metadata?: Metadata; error?: string; errorType?: 'action' | 'validation' | 'resource' } -interface Actions { items(target: SessionActionTarget): MenuItem[]; prepare(open: boolean): void } +interface Actions { items(target: SessionActionTarget): MenuItem[]; prepare(open: boolean): void; archive(target: SessionActionTarget, archived: boolean): Promise } const ActionsContext = createContext(null); const aliasKey = (runtimeId: string) => `whip.web.editor-ssh.v1:${runtimeId}`; @@ -141,8 +141,15 @@ export function SessionActionsProvider({ children }: { children: ReactNode }) { } async function archive(target: SessionActionTarget, archived: boolean) { await perform(async () => { - const client = attached(target).client!; - await runtime.run(client.session(target.rootId).archive(archived), archived ? 'Archive session' : 'Restore session'); + const host = attached(target); + const client = host.client!; + host.list?.setOptimisticArchived(target.rootId, archived); + try { + await runtime.run(client.session(target.rootId).archive(archived), archived ? 'Archive session' : 'Restore session'); + } catch (error) { + host.list?.setOptimisticArchived(target.rootId, !archived); + throw error; + } toast.add({ title: archived ? 'Session archived' : 'Session restored', description: archived ? : 'This session is back in the sidebar.' }); @@ -157,6 +164,12 @@ export function SessionActionsProvider({ children }: { children: ReactNode }) { else { await runtime.platform.copy(data.cwd); toast.add({ title: 'Directory copied' }); } }, target, app ? 'Could not open directory' : 'Could not copy directory'); } + async function copyId(target: SessionActionTarget) { + await perform(async () => { + await runtime.platform.copy(target.rootId); + toast.add({ title: 'Session ID copied', description: target.rootId }); + }, target, 'Could not copy session ID'); + } const prepare = (open: boolean) => { if (!open || !runtime.platform.projectEditors) return; setEditorError(undefined); @@ -181,6 +194,7 @@ export function SessionActionsProvider({ children }: { children: ReactNode }) { { id: 'background', label: 'Open in background tab', disabled, onSelect: () => { try { runtime.tabs.open(target.runtimeId, target.rootId, target.title); } catch (error) { setFailure({ target, title: 'Could not open session tab', error }); } } }, { id: 'open-in', label: 'Open in', disabled, items: [...native, { id: 'copy-directory', label: 'Copy directory', disabled, onSelect: () => void openDirectory(target) }] }, { id: 'rename', label: 'Rename', disabled, onSelect: () => void begin(target, 'rename') }, + { id: 'copy-id', label: 'Copy session ID', disabled: busy || !host, onSelect: () => void copyId(target) }, { id: 'fork', label: 'Fork', disabled, onSelect: () => void begin(target, 'fork') }, { id: 'archive', label: target.archived ? 'Restore' : 'Archive', disabled, onSelect: () => void archive(target, !target.archived) }, { id: 'destructive-separator', label: '', separator: true }, @@ -188,7 +202,7 @@ export function SessionActionsProvider({ children }: { children: ReactNode }) { ]; } const title = selection?.action === 'rename' ? 'Rename session' : selection?.action === 'delete' ? 'Delete this session?' : selection?.action === 'ssh' ? 'SSH for editors' : 'Fork session'; - return {children} + return {children} { if (!open) close(); }} title={title} description={selection?.action === 'delete' ? 'This permanently deletes the session, its owned work, and unsent drafts. Running work will stop. Files in the working directory stay on disk.' : selection?.action === 'ssh' ? 'Use an SSH config alias on this computer. The editor handles SSH authentication. This setting applies to this Whip host on this device.' : undefined} footer={<>{selection?.action !== 'fork' && {actions.items({ runtimeId: 'remote', rootId: 'same-root', title: 'Truncated…' }).flatMap(item => item.items ?? [item]).map(item => )} : null; + return visible ? <>{actions.items({ runtimeId: 'remote', rootId: 'same-root', title: 'Truncated…' }).flatMap(item => item.items ?? [item]).map(item => )} : null; } function fixture() { const metadata = { root_id: 'same-root', title: 'The full title behind the truncated catalog', cwd: '/full/directory', archived: false, history_revision: '42' }; @@ -19,7 +19,8 @@ function fixture() { const rename = vi.fn(() => 'rename-command'), fork = vi.fn(() => 'fork-command'), archive = vi.fn(() => 'archive-command'), remove = vi.fn(() => 'delete-command'); const session = vi.fn(() => ({ rename, fork, archive, delete: remove })); const client = { sessions: { get }, session }; - const host = { id: 'remote-profile', name: 'Remote workstation', client, state: 'connected', profile: { target: { kind: 'url' } } }; + const list = { setOptimisticArchived: vi.fn() }; + const host = { id: 'remote-profile', name: 'Remote workstation', client, list, state: 'connected', profile: { target: { kind: 'url' } } }; const snapshot = { hosts: [host] }; const run = vi.fn(async () => ({ result: { root_id: 'forked' } })); const workspace = { tabs: [], layout: { type: 'pane', id: 'main', tabs: [] }, focusedPaneId: 'main', closed: [] }; @@ -29,7 +30,7 @@ function fixture() { forgetSession: vi.fn(), run, report: vi.fn(), reportWorkspace: vi.fn() } as unknown as AppRuntime; const tree = (visible = true) => ; const view = render(tree()); - return { get, metadata, rename, fork, archive, remove, session, host, runtime, run, workspace, rerender: (visible = true) => view.rerender(tree(visible)) }; + return { get, metadata, rename, fork, archive, remove, session, host, list, runtime, run, workspace, rerender: (visible = true) => view.rerender(tree(visible)) }; } it('Open in new tab opens a fresh selected root chat without session work, while background still reuses', async () => { const f = fixture(); @@ -61,6 +62,19 @@ it('Open in new tab permits known offline hosts but disables removed hosts', () expect(screen.getByRole('button', { name: 'Open in new tab', exact: true }).hasAttribute('disabled')).toBe(true); }); +it('Copy session ID copies the root id, works offline, and reports failures', async () => { + const f = fixture(); + fireEvent.click(screen.getByRole('button', { name: 'Copy session ID', exact: true })); + await waitFor(() => expect(f.runtime.platform.copy).toHaveBeenCalledExactlyOnceWith('same-root')); + await screen.findByText('Session ID copied'); + expect(f.get).not.toHaveBeenCalled(); expect(f.run).not.toHaveBeenCalled(); + f.host.state = 'disconnected'; f.rerender(); + expect(screen.getByRole('button', { name: 'Copy session ID', exact: true }).hasAttribute('disabled')).toBe(false); + vi.spyOn(f.runtime.platform, 'copy').mockRejectedValueOnce(new Error('no clipboard')); + fireEvent.click(screen.getByRole('button', { name: 'Copy session ID', exact: true })); + expect(await screen.findByText('Could not copy session ID')).toBeTruthy(); +}); + it('Open in new tab reports full capacity without navigating', async () => { const f = fixture(); const tabs = new SessionTabs(); @@ -141,6 +155,30 @@ it('archive keeps tabs and drafts, with an Undo that restores the same root', as await waitFor(() => expect(f.archive).toHaveBeenLastCalledWith(false)); expect(f.session.mock.calls.every(args => args[0] === 'same-root')).toBe(true); }); +it('hover archive button archives without a dialog and offers Undo, keeping any open tab', async () => { + const f = fixture(); + route.location = { pathname: '/h/remote/s/same-root' }; + fireEvent.click(screen.getByRole('button', { name: 'Archive hover button', exact: true })); + expect(f.list.setOptimisticArchived).toHaveBeenCalledExactlyOnceWith('same-root', true); + expect(await screen.findByText('Session archived')).toBeTruthy(); + await waitFor(() => expect(f.archive).toHaveBeenCalledExactlyOnceWith(true)); + expect(screen.queryByText('Delete this session?')).toBeNull(); + expect(screen.queryByText('Could not archive session')).toBeNull(); + expect(route.navigate).not.toHaveBeenCalled(); + expect(f.runtime.forgetSession).not.toHaveBeenCalled(); + fireEvent.click(await screen.findByRole('button', { name: 'Undo archive' })); + await waitFor(() => expect(f.archive).toHaveBeenLastCalledWith(false)); + expect(f.list.setOptimisticArchived).toHaveBeenLastCalledWith('same-root', false); +}); +it('a failed archive reverts the optimistic removal', async () => { + const f = fixture(); + f.run.mockRejectedValueOnce(new Error('Archive rejected')); + fireEvent.click(screen.getByRole('button', { name: 'Archive hover button', exact: true })); + expect(f.list.setOptimisticArchived).toHaveBeenCalledExactlyOnceWith('same-root', true); + await screen.findByRole('dialog', { name: 'Could not archive session' }); + expect(f.list.setOptimisticArchived).toHaveBeenLastCalledWith('same-root', false); + expect(screen.queryByText('Session archived')).toBeNull(); +}); it('browser Copy directory uses full metadata rather than the catalog abbreviation', async () => { const f = fixture(); fireEvent.click(screen.getByRole('button', { name: 'Copy directory', exact: true })); diff --git a/packages/app/test/session-tab-titles.test.tsx b/packages/app/test/session-tab-titles.test.tsx new file mode 100644 index 000000000..1fd56b21d --- /dev/null +++ b/packages/app/test/session-tab-titles.test.tsx @@ -0,0 +1,112 @@ +import type { ReactNode } from 'react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; +import { QueryClientProvider } from '@tanstack/react-query'; +import { afterEach, expect, it, vi } from 'vitest'; +import { UIProvider } from '@whip/ui'; +import type { WhipClient } from '@whip/sdk'; +import type { SessionSummariesResult } from '@whip/protocol'; +import { AppRuntime } from '../src/runtime'; +import { RuntimeContext } from '../src/context'; +import { SessionTabStrip } from '../src/session-tab-strip'; +import { SessionActionsProvider, useSessionActions } from '../src/session-actions'; + +const roots = vi.hoisted(() => vi.fn()); +const connection = vi.hoisted(() => ({ client: undefined as WhipClient | undefined })); +vi.mock('@whip/sdk', async importOriginal => ({ ...await importOriginal(), createWhipClient: () => connection.client })); +vi.mock('@whip/sdk/state', async importOriginal => ({ ...await importOriginal(), createSessionListView: () => ({ start: async () => {}, dispose: async () => {}, getSnapshot: () => ({}) }) })); +vi.mock('@tanstack/react-router', () => ({ + Link: ({ children }: { children: ReactNode }) => {children}, + useLocation: () => ({ pathname: '/h/mac/s/active' }), useNavigate: () => vi.fn(), +})); +vi.mock('../src/conversation', () => ({ SessionContent: () => null, SessionLoading: () => null })); +vi.mock('../src/workspace-views', () => ({ + useWorkspaceViews: (_runtime: unknown, requested: unknown) => { roots(requested); return { views: new Map(), errors: new Map() }; }, + workspaceRootKey: ({ runtimeId, rootId }: { runtimeId: string; rootId: string }) => JSON.stringify([runtimeId, rootId]), +})); +// Layout geometry and transcript ownership have separate tests; keep the real summary query and tab store. +vi.mock('@whip/ui/workspace-tabs', () => ({ + WorkspaceTabs: ({ items, value }: { items: { value: string; label: ReactNode }[]; value: string }) =>
{items.map(item => )}
, + workspaceTabId: (id: string) => id, +})); +vi.mock('@whip/ui/workspace-layout', () => ({ + WorkspaceLayout: ({ renderHeader, layout }: { renderHeader(id: string): ReactNode; layout: { id: string } }) => <>{renderHeader(layout.id)}, + workspacePanelId: (id: string) => id, +})); +afterEach(() => { vi.useRealTimers(); vi.unstubAllGlobals(); }); +function RenameInactive() { + const actions = useSessionActions(); + return ; +} + +it.each([false, true])('updates inactive tab titles without root streams (notification: %s)', async notification => { + vi.useFakeTimers(); + vi.stubGlobal('matchMedia', () => ({ matches: false, addEventListener() {}, removeEventListener() {} })); + vi.stubGlobal('ResizeObserver', class { observe() {} unobserve() {} disconnect() {} }); + const disk = new Map(); + const runtime = new AppRuntime({ defaultEndpoint: 'http://localhost:8080', + storage: { keys: () => [...disk.keys()], getItem: key => disk.get(key) ?? null, setItem: (key, value) => { disk.set(key, value); }, removeItem: key => { disk.delete(key); } }, + copy: async () => {}, openExternal: async () => {}, download: async () => 'saved', sessionLink: value => value, + }); + const summary = (root_id: string, title: string): SessionSummariesResult['items'][number] => ({ + root_id, title, missing: false, archived: false, cwd: '/work', running_agents: '0', queued_agents: '0', + pending_permissions: '0', pending_questions: '0', truncated: false, + }); + let items = [summary('active', 'Active conversation'), summary('inactive', 'Help me repair the build')]; + const summaries = vi.fn(async () => ({ items: structuredClone(items) })); + const subscribe = vi.fn(); + const session = vi.fn(); + const connected = { state: 'connected', info: { runtime_id: 'mac', connection_id: 'connection', negotiated_capabilities: ['session_summaries', ...(notification ? ['session_title_notifications'] : [])] } }; + const titleListeners = new Set<(params: { root_id: string }) => void>(); + connection.client = { getSnapshot: () => connected, sessions: { summaries, list: async () => ({ items: [] }), get: async () => ({ root_id: 'inactive', title: items[1]!.title, cwd: '/work', archived: false, history_revision: '1' }) }, events: { subscribe }, session, + configuration: { get: async () => ({ revision: '1', remote_hosts: [] }) }, + providers: { list: async () => ({}), catalogs: async () => ({}) }, + onNotification: (method: string, listener: (params: { root_id: string }) => void) => { + expect(method).toBe('sessions.title.changed'); titleListeners.add(listener); return () => titleListeners.delete(listener); + }, + subscribe: () => () => {}, connect: async () => {}, onEvent: () => () => {}, close: vi.fn(), + } as unknown as WhipClient; + await runtime.connect(); + runtime.tabs.open('mac', 'inactive'); + runtime.tabs.open('mac', 'active'); + runtime.tabs.visit('mac', 'active', {}); + const view = render( + {}} utilities={null} /> + ); + try { + await act(async () => { await vi.advanceTimersByTimeAsync(1); }); + expect(screen.getByRole('tab', { name: 'Help me repair the build' }).getAttribute('aria-selected')).toBe('false'); + expect(summaries).toHaveBeenCalledWith(['active', 'inactive'], { signal: expect.any(AbortSignal) }); + if (notification) { + await act(async () => { fireEvent.click(screen.getByRole('button', { name: 'Rename inactive' })); }); + fireEvent.change(screen.getByRole('textbox'), { target: { value: 'My unsent rename' } }); + } + const before = summaries.mock.calls.length; + // The daemon persisted a generated title; no root event or local command is delivered here. + items = [items[0]!, summary('inactive', 'Repair build')]; + for (const listener of titleListeners) listener({ root_id: 'inactive' }); + await act(async () => { await vi.advanceTimersByTimeAsync(notification ? 251 : 2001); }); + expect(titleListeners.size).toBe(notification ? 1 : 0); + if (notification) { + expect((screen.getByRole('textbox') as HTMLInputElement).value).toBe('My unsent rename'); + await act(async () => { fireEvent.click(screen.getByLabelText('Close', { exact: true })); }); + } + expect(summaries.mock.calls.length).toBeGreaterThan(before); + expect(screen.getByRole('tab', { name: 'Repair build' }).getAttribute('aria-selected')).toBe('false'); + expect(screen.getByRole('tab', { name: 'Active conversation' }).getAttribute('aria-selected')).toBe('true'); + expect(runtime.tabs.workspace().tabs.find(tab => tab.kind === 'chat' && tab.rootId === 'inactive')?.titleHint).toBe('Repair build'); + if (notification) { + // A missed hint is still recovered by the original two-second summary poll. + items = [items[0]!, summary('inactive', 'Recovered by polling')]; + await act(async () => { await vi.advanceTimersByTimeAsync(2001); }); + expect(screen.getByRole('tab', { name: 'Recovered by polling' }).getAttribute('aria-selected')).toBe('false'); + } + expect(roots).toHaveBeenCalled(); + expect(roots.mock.calls.every(([requested]) => requested.length === 1 && requested[0].rootId === 'active')).toBe(true); + expect(session).not.toHaveBeenCalled(); + expect(subscribe).not.toHaveBeenCalled(); + } finally { + view.unmount(); + runtime.dispose(); + expect(titleListeners.size).toBe(0); + } +}); diff --git a/packages/app/test/session-title-notifications.test.ts b/packages/app/test/session-title-notifications.test.ts new file mode 100644 index 000000000..749e8f0bc --- /dev/null +++ b/packages/app/test/session-title-notifications.test.ts @@ -0,0 +1,137 @@ +import { afterEach, expect, it, vi } from 'vitest'; +import { QueryObserver } from '@tanstack/react-query'; +import type { WhipClient } from '@whip/sdk'; +import { AppRuntime } from '../src/runtime'; +import { createFallbackStorage } from '../src/platform'; + +const clients = vi.hoisted(() => new Map()); +vi.mock('@whip/sdk', async importOriginal => ({ ...await importOriginal(), createWhipClient: (options: { endpoint: string }) => clients.get(new URL(options.endpoint).hostname) })); +vi.mock('@whip/sdk/state', () => ({ createSessionListView: () => ({ start: async () => {}, dispose: async () => {} }) })); +const apps: AppRuntime[] = []; +afterEach(() => { apps.splice(0).forEach(app => app.dispose()); clients.clear(); vi.useRealTimers(); }); + +function host(runtimeId: string, supported = true) { + const listeners = new Set<() => void>(); + const titles = new Set<(params: { root_id: string }) => void>(); + const snapshot = { state: 'connected', info: { runtime_id: runtimeId, connection_id: '1', negotiated_capabilities: supported ? ['session_title_notifications'] : [] } }; + const client = { getSnapshot: () => snapshot, subscribe: (listener: () => void) => { listeners.add(listener); return () => listeners.delete(listener); }, + onNotification: vi.fn((method: string, listener: (params: { root_id: string }) => void) => { + expect(method).toBe('sessions.title.changed'); titles.add(listener); return () => titles.delete(listener); + }), + configuration: { get: vi.fn(async () => ({ revision: '1', remote_hosts: [] as { id: string; name: string; url: string; runtime_id: string; connect_on_launch: boolean }[] })) }, + providers: { list: async () => ({}), catalogs: async () => ({}) }, sessions: { list: async () => ({ items: [] }) }, + session: vi.fn(), events: { subscribe: vi.fn() }, connect: async () => {}, close: vi.fn(), + }; + clients.set(runtimeId, client as unknown as WhipClient); + return { client, titles, snapshot, notify: (root_id = 'unopened') => { for (const listener of titles) listener({ root_id }); }, + state: (state: string, connection_id = snapshot.info.connection_id) => { snapshot.state = state; snapshot.info.connection_id = connection_id; for (const listener of listeners) listener(); } }; +} +async function setup(supported = true) { + vi.useFakeTimers(); + const local = host('local', supported); + const remote = host('remote', supported); + local.client.configuration.get.mockResolvedValue({ revision: '1', remote_hosts: [{ id: 'remote', name: 'Remote', url: 'http://remote', runtime_id: 'remote', connect_on_launch: false }] }); + const app = new AppRuntime({ defaultEndpoint: 'http://local', storage: createFallbackStorage(() => { throw new Error('memory only'); }, () => {}), copy: async () => {}, download: async () => {}, openExternal: async () => {} }); + apps.push(app); + await app.connect(); await app.connections.refreshProfiles(); await app.connections.connect('remote'); + return { app, local, remote }; +} + +it('coalesces title hints across host-scoped title queries, refreshing all searches but not inactive caches or other hosts', async () => { + const { app, local, remote } = await setup(); + app.queries.setDefaultOptions({ queries: { ...app.queries.getDefaultOptions().queries, gcTime: Infinity } }); + let title = 'Before'; + const keys = [ + ['session-tab-summaries', 'local', ['inactive']], ['session-sidebar-summaries', 'local', ['visible']], + ['session-search', 'local', 'before', 'all', 'page-2'], ['session-search', 'local', 'after', 'all', undefined], + ['host-attention', 'local', 'cursor'], + ]; + const reads = keys.map(key => vi.fn(async () => key[0] === 'session-search' ? (title.toLowerCase() === key[2] ? [title] : []) : title)); + const observers = keys.map((queryKey, index) => new QueryObserver(app.queries, { queryKey, queryFn: reads[index]!, staleTime: Infinity })); + const stops = observers.map(observer => observer.subscribe(() => {})); + await Promise.all(observers.map(observer => observer.refetch())); + const inactiveKey = ['session-search', 'local', 'inactive']; + app.queries.setQueryData(inactiveKey, 'cached'); + const remoteKey = ['session-tab-summaries', 'remote', ['inactive']]; + app.queries.setQueryData(remoteKey, 'Other host'); + const providerKey = ['provider-list', 'local']; + app.queries.setQueryData(providerKey, 'Provider settings'); + const providers = app.queries.getQueryState(providerKey); + const remoteBefore = app.queries.getQueryState(remoteKey); + title = 'After'; + for (let i = 0; i < 20; i++) local.notify('off-page-root'); + await vi.advanceTimersByTimeAsync(251); + reads.forEach(read => expect(read).toHaveBeenCalledTimes(2)); + expect(app.queries.getQueryData(keys[0]!)).toBe('After'); + expect(app.queries.getQueryData(keys[2]!)).toEqual([]); + expect(app.queries.getQueryData(keys[3]!)).toEqual(['After']); + expect(app.queries.getQueryState(inactiveKey)?.isInvalidated).toBe(true); + expect(app.queries.getQueryData(inactiveKey)).toBe('cached'); + expect(app.queries.getQueryState(remoteKey)).toEqual(remoteBefore); + expect(app.queries.getQueryState(providerKey)).toEqual(providers); + expect(local.titles.size).toBe(1); expect(remote.titles.size).toBe(1); + expect(local.client.session).not.toHaveBeenCalled(); expect(local.client.events.subscribe).not.toHaveBeenCalled(); + stops.forEach(stop => stop()); +}); + +it.each([false, true])('cancels stale in-flight title reads even when it is the initial load (%s)', async initial => { + const { app, local } = await setup(); + const key = ['session-tab-summaries', 'local', ['inactive']]; + if (!initial) app.queries.setQueryData(key, 'Previously cached'); + let finish!: (title: string) => void; + let signal!: AbortSignal; + const read = vi.fn(({ signal: requestSignal }: { signal: AbortSignal }) => { + signal = requestSignal; + return new Promise(resolve => { finish = resolve; }); + }); + const observer = new QueryObserver(app.queries, { queryKey: key, queryFn: read, staleTime: 0 }); + const stop = observer.subscribe(() => {}); + const oldFinish = finish, oldSignal = signal; + local.notify(); await vi.advanceTimersByTimeAsync(251); + expect(oldSignal.aborted).toBe(true); + expect(read).toHaveBeenCalledTimes(2); + const intermediateFinish = finish, intermediateSignal = signal; + for (let i = 0; i < 20; i++) local.notify(); + await vi.advanceTimersByTimeAsync(251); + expect(intermediateSignal.aborted).toBe(true); + expect(read).toHaveBeenCalledTimes(3); + finish('Newest'); await vi.advanceTimersByTimeAsync(1); + intermediateFinish('Intermediate'); + oldFinish('Stale'); await vi.advanceTimersByTimeAsync(1); + expect(app.queries.getQueryData(key)).toBe('Newest'); + stop(); +}); + +it('owns one listener through reconnect and retires timers and pending cancellation on detach/dispose', async () => { + const { app, local, remote } = await setup(); + const key = ['session-tab-summaries', 'local', ['inactive']]; + const invalidations = vi.spyOn(app.queries, 'invalidateQueries'); + local.notify(); local.state('reconnecting'); + await vi.advanceTimersByTimeAsync(251); + expect(invalidations).not.toHaveBeenCalled(); + local.state('connected', '2'); local.state('connected', '2'); + expect(local.titles.size).toBe(1); + expect(local.client.onNotification).toHaveBeenCalledTimes(2); + invalidations.mockClear(); + let finish!: () => void; + vi.spyOn(app.queries, 'cancelQueries').mockImplementationOnce(() => new Promise(resolve => { finish = resolve; })); + app.queries.setQueryData(key, 'Before detach'); + local.notify(); await vi.advanceTimersByTimeAsync(251); + const retired = [...local.titles][0]!; + app.connections.disconnect('local'); + expect(local.titles.size).toBe(0); + finish(); retired({ root_id: 'late' }); await vi.advanceTimersByTimeAsync(251); + expect(invalidations).not.toHaveBeenCalled(); + expect(app.queries.getQueryData(key)).toBeUndefined(); + expect(remote.titles.size).toBe(1); + remote.notify(); app.dispose(); await vi.advanceTimersByTimeAsync(251); + expect(remote.titles.size).toBe(0); + expect(invalidations).not.toHaveBeenCalled(); +}); + +it('does not register an app title listener for older hosts', async () => { + const { app, local, remote } = await setup(false); + expect(local.client.onNotification).not.toHaveBeenCalled(); + expect(remote.client.onNotification).not.toHaveBeenCalled(); + app.dispose(); +}); diff --git a/packages/app/test/settings-agents.test.tsx b/packages/app/test/settings-agents.test.tsx index b13c777c4..62201f199 100644 --- a/packages/app/test/settings-agents.test.tsx +++ b/packages/app/test/settings-agents.test.tsx @@ -109,4 +109,6 @@ it('round-trips a definition through the editor values', () => { const document = agentDocument(values); expect(document).toEqual({ ...triage, instructions: { ...triage.instructions, project_files: null }, model: triage.model }); expect(agentValues(coding, true).id).toBe('coding-custom'); + const optedOut = { ...triage, surface: { ...triage.surface, auto_title: false } }; + expect(agentDocument(agentValues(optedOut, false)).surface.auto_title).toBe(false); }); diff --git a/packages/protocol/generated/index.d.ts b/packages/protocol/generated/index.d.ts index 367b2f5af..22047bb23 100644 --- a/packages/protocol/generated/index.d.ts +++ b/packages/protocol/generated/index.d.ts @@ -3681,6 +3681,10 @@ export interface SessionSummariesResult { }[]; } +export interface SessionTitleChangedParams { + root_id: string; +} + export interface SessionUpdateEvent { archived?: null | boolean; title?: string; @@ -4205,6 +4209,7 @@ export interface ContractTypes { SessionPreviewResult: SessionPreviewResult; SessionSummariesParams: SessionSummariesParams; SessionSummariesResult: SessionSummariesResult; + SessionTitleChangedParams: SessionTitleChangedParams; SessionUpdateEvent: SessionUpdateEvent; ShellParams: ShellParams; SnapshotParams: SnapshotParams; @@ -4462,7 +4467,6 @@ export interface RuntimeOperations { "schedule.delete": { params: ScheduleDeleteParams; result: ScheduleResult; execution: "command"; permission: "root-association"; sensitive: false }; "schedule.list": { params: EmptyParams; result: ScheduleListResult; execution: "query"; permission: "root-association"; sensitive: false }; "session.archive": { params: ArchiveParams; result: ArchiveResult; execution: "command"; permission: "root-association"; sensitive: false }; - "session.autotitle": { params: EmptyParams; result: Empty; execution: "command"; permission: "root-association"; sensitive: false }; "session.create": { params: CreateSessionParams; result: RootIDResult; execution: "command"; permission: "host-runtime"; sensitive: false }; "session.delete": { params: RootParams; result: RootIDResult; execution: "command"; permission: "root-association"; sensitive: false }; "session.effort": { params: EffortParams; result: EffortResult; execution: "command"; permission: "root-idle"; sensitive: false }; diff --git a/packages/protocol/generated/index.js b/packages/protocol/generated/index.js index 923993f9b..cbd64f78f 100644 --- a/packages/protocol/generated/index.js +++ b/packages/protocol/generated/index.js @@ -1005,14 +1005,6 @@ export const manifest = { "params_type": "ArchiveParams", "result_type": "ArchiveResult" }, - { - "name": "session.autotitle", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "Empty" - }, { "name": "session.create", "surface": "runtime", @@ -1191,6 +1183,7 @@ export const manifest = { "event": "EventNotification", "hook.cancel": "ToolCancelParams", "hook.invoke": "HookInvokeParams", + "sessions.title.changed": "SessionTitleChangedParams", "subscription.failed": "SubscriptionFailure", "terminal.detached": "TerminalDetachedParams", "terminal.exited": "TerminalExitedParams", diff --git a/packages/protocol/generated/request-validators.js b/packages/protocol/generated/request-validators.js index 8c4d62a85..434c4e6d7 100644 --- a/packages/protocol/generated/request-validators.js +++ b/packages/protocol/generated/request-validators.js @@ -66576,10 +66576,67 @@ validate172.errors = vErrors; return errors === 0; } -export const SessionUpdateEvent = validate173; -const schema174 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":false}; +export const SessionTitleChangedParams = validate173; +const schema174 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionTitleChangedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionTitleChangedParams","required":["root_id"],"additionalProperties":false}; function validate173(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +/*# sourceURL="https://whip.dev/protocol/v6/SessionTitleChangedParams" */; +let vErrors = null; +let errors = 0; +if(data && typeof data == "object" && !Array.isArray(data)){ +if(data.root_id === undefined){ +const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; +if(vErrors === null){ +vErrors = [err0]; +} +else { +vErrors.push(err0); +} +errors++; +} +for(const key0 in data){ +if(!(key0 === "root_id")){ +const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; +if(vErrors === null){ +vErrors = [err1]; +} +else { +vErrors.push(err1); +} +errors++; +} +} +if(data.root_id !== undefined){ +if(typeof data.root_id !== "string"){ +const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; +if(vErrors === null){ +vErrors = [err2]; +} +else { +vErrors.push(err2); +} +errors++; +} +} +} +else { +const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; +if(vErrors === null){ +vErrors = [err3]; +} +else { +vErrors.push(err3); +} +errors++; +} +validate173.errors = vErrors; +return errors === 0; +} + +export const SessionUpdateEvent = validate174; +const schema175 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":false}; + +function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SessionUpdateEvent" */; let vErrors = null; let errors = 0; @@ -66599,7 +66656,7 @@ errors++; if(data.archived !== undefined){ let data0 = data.archived; if((data0 !== null) && (typeof data0 !== "boolean")){ -const err1 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema174.properties.archived.type},message:"must be null,boolean"}; +const err1 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema175.properties.archived.type},message:"must be null,boolean"}; if(vErrors === null){ vErrors = [err1]; } @@ -66684,7 +66741,7 @@ errors++; if(data.permission_mode !== undefined){ let data7 = data.permission_mode; if((data7 !== null) && (typeof data7 !== "string")){ -const err8 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema174.properties.permission_mode.type},message:"must be null,string"}; +const err8 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema175.properties.permission_mode.type},message:"must be null,string"}; if(vErrors === null){ vErrors = [err8]; } @@ -66705,14 +66762,14 @@ vErrors.push(err9); } errors++; } -validate173.errors = vErrors; +validate174.errors = vErrors; return errors === 0; } -export const ShellParams = validate174; -const schema175 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":false}; +export const ShellParams = validate175; +const schema176 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":false}; -function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ShellParams" */; let vErrors = null; let errors = 0; @@ -66762,14 +66819,14 @@ vErrors.push(err3); } errors++; } -validate174.errors = vErrors; +validate175.errors = vErrors; return errors === 0; } -export const SnapshotParams = validate175; -const schema176 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":false}; +export const SnapshotParams = validate176; +const schema177 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":false}; -function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SnapshotParams" */; let vErrors = null; let errors = 0; @@ -66819,14 +66876,14 @@ vErrors.push(err3); } errors++; } -validate175.errors = vErrors; +validate176.errors = vErrors; return errors === 0; } -export const SpanPage = validate176; -const schema177 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":false}; +export const SpanPage = validate177; +const schema178 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":false}; -function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SpanPage" */; let vErrors = null; let errors = 0; @@ -66908,7 +66965,7 @@ errors++; if(data.spans !== undefined){ let data1 = data.spans; if((data1 !== null) && (!(Array.isArray(data1)))){ -const err7 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema177.properties.spans.type},message:"must be null,array"}; +const err7 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema178.properties.spans.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err7]; } @@ -67023,7 +67080,7 @@ vErrors.push(err17); errors++; } for(const key1 in data2){ -if(!(func2.call(schema177.properties.spans.items.properties, key1))){ +if(!(func2.call(schema178.properties.spans.items.properties, key1))){ const err18 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; if(vErrors === null){ vErrors = [err18]; @@ -67354,14 +67411,14 @@ vErrors.push(err45); } errors++; } -validate176.errors = vErrors; +validate177.errors = vErrors; return errors === 0; } -export const SpanRecord = validate177; -const schema178 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}; +export const SpanRecord = validate178; +const schema179 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}; -function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SpanRecord" */; let vErrors = null; let errors = 0; @@ -67467,7 +67524,7 @@ vErrors.push(err9); errors++; } for(const key0 in data){ -if(!(func2.call(schema178.properties, key0))){ +if(!(func2.call(schema179.properties, key0))){ const err10 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; if(vErrors === null){ vErrors = [err10]; @@ -67702,20 +67759,20 @@ vErrors.push(err29); } errors++; } -validate177.errors = vErrors; +validate178.errors = vErrors; return errors === 0; } -export const StreamEvent = validate178; -const schema179 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false}},"required":["used","size","usage"],"additionalProperties":false},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":false}; +export const StreamEvent = validate179; +const schema180 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false}},"required":["used","size","usage"],"additionalProperties":false},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":false}; -function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/StreamEvent" */; let vErrors = null; let errors = 0; if(data && typeof data == "object" && !Array.isArray(data)){ for(const key0 in data){ -if(!(func2.call(schema179.properties, key0))){ +if(!(func2.call(schema180.properties, key0))){ const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; if(vErrors === null){ vErrors = [err0]; @@ -67741,7 +67798,7 @@ errors++; if(data.display !== undefined){ let data1 = data.display; if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err2 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema179.properties.display.type},message:"must be null,object"}; +const err2 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema180.properties.display.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err2]; } @@ -67828,7 +67885,7 @@ errors++; if(data.accounting !== undefined){ let data7 = data.accounting; if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema179.properties.accounting.type},message:"must be null,object"}; +const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema180.properties.accounting.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err9]; } @@ -67959,7 +68016,7 @@ vErrors.push(err21); errors++; } for(const key2 in data7){ -if(!(func2.call(schema179.properties.accounting.properties, key2))){ +if(!(func2.call(schema180.properties.accounting.properties, key2))){ const err22 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; if(vErrors === null){ vErrors = [err22]; @@ -68326,7 +68383,7 @@ errors++; if(data.usage !== undefined){ let data20 = data.usage; if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err53 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema179.properties.usage.type},message:"must be null,object"}; +const err53 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema180.properties.usage.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err53]; } @@ -68454,7 +68511,7 @@ errors++; if(data23.cost !== undefined){ let data25 = data23.cost; if((data25 !== null) && (!(typeof data25 == "number"))){ -const err64 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; +const err64 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; if(vErrors === null){ vErrors = [err64]; } @@ -68493,7 +68550,7 @@ errors++; if(data23.prompt_tokens_details !== undefined){ let data28 = data23.prompt_tokens_details; if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err67 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; +const err67 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err67]; } @@ -68543,7 +68600,7 @@ errors++; if(data23.completion_tokens_details !== undefined){ let data30 = data23.completion_tokens_details; if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err71 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; +const err71 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err71]; } @@ -68735,14 +68792,14 @@ vErrors.push(err86); } errors++; } -validate178.errors = vErrors; +validate179.errors = vErrors; return errors === 0; } -export const SubmitPayload = validate179; -const schema180 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":false}; +export const SubmitPayload = validate180; +const schema181 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":false}; -function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubmitPayload" */; let vErrors = null; let errors = 0; @@ -68772,7 +68829,7 @@ errors++; if(data.design_context !== undefined){ let data0 = data.design_context; if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema180.properties.design_context.type},message:"must be null,object"}; +const err2 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema181.properties.design_context.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err2]; } @@ -68851,7 +68908,7 @@ errors++; if(data0.elements !== undefined){ let data3 = data0.elements; if((data3 !== null) && (!(Array.isArray(data3)))){ -const err9 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema180.properties.design_context.properties.elements.type},message:"must be null,array"}; +const err9 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema181.properties.design_context.properties.elements.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err9]; } @@ -68979,7 +69036,7 @@ errors++; if(data.parts !== undefined){ let data11 = data.parts; if((data11 !== null) && (!(Array.isArray(data11)))){ -const err19 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema180.properties.parts.type},message:"must be null,array"}; +const err19 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema181.properties.parts.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err19]; } @@ -69042,7 +69099,7 @@ errors++; if(data12.image_url !== undefined){ let data15 = data12.image_url; if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err24 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema180.properties.parts.items.properties.image_url.type},message:"must be null,object"}; +const err24 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema181.properties.parts.items.properties.image_url.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err24]; } @@ -69131,7 +69188,7 @@ errors++; if(data.attachments !== undefined){ let data19 = data.attachments; if((data19 !== null) && (!(Array.isArray(data19)))){ -const err31 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema180.properties.attachments.type},message:"must be null,array"}; +const err31 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema181.properties.attachments.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err31]; } @@ -69190,7 +69247,7 @@ vErrors.push(err35); errors++; } if(!((data21 === "image") || (data21 === "text"))){ -const err36 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema180.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; +const err36 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema181.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; if(vErrors === null){ vErrors = [err36]; } @@ -69377,14 +69434,14 @@ vErrors.push(err51); } errors++; } -validate179.errors = vErrors; +validate180.errors = vErrors; return errors === 0; } -export const SubscribeParams = validate180; -const schema181 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":false}; +export const SubscribeParams = validate181; +const schema182 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":false}; -function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscribeParams" */; let vErrors = null; let errors = 0; @@ -69501,14 +69558,14 @@ vErrors.push(err9); } errors++; } -validate180.errors = vErrors; +validate181.errors = vErrors; return errors === 0; } -export const SubscribeResult = validate181; -const schema182 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":false}; +export const SubscribeResult = validate182; +const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":false}; -function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscribeResult" */; let vErrors = null; let errors = 0; @@ -69603,14 +69660,14 @@ vErrors.push(err7); } errors++; } -validate181.errors = vErrors; +validate182.errors = vErrors; return errors === 0; } -export const SubscriptionFailure = validate182; -const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":false},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":false}; +export const SubscriptionFailure = validate183; +const schema184 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":false},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":false}; -function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscriptionFailure" */; let vErrors = null; let errors = 0; @@ -69684,7 +69741,7 @@ errors++; if(data.error !== undefined){ let data2 = data.error; if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err6 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema183.properties.error.type},message:"must be null,object"}; +const err6 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema184.properties.error.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err6]; } @@ -69729,7 +69786,7 @@ errors++; if(data2.data !== undefined){ let data3 = data2.data; if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err10 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema183.properties.error.properties.data.type},message:"must be null,object"}; +const err10 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema184.properties.error.properties.data.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err10]; } @@ -69813,14 +69870,14 @@ vErrors.push(err16); } errors++; } -validate182.errors = vErrors; +validate183.errors = vErrors; return errors === 0; } -export const TerminalAttachParams = validate183; -const schema184 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":false}; +export const TerminalAttachParams = validate184; +const schema185 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":false}; -function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachParams" */; let vErrors = null; let errors = 0; @@ -69915,14 +69972,14 @@ vErrors.push(err7); } errors++; } -validate183.errors = vErrors; +validate184.errors = vErrors; return errors === 0; } -export const TerminalAttachResult = validate184; -const schema185 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":false}; +export const TerminalAttachResult = validate185; +const schema186 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":false}; -function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachResult" */; let vErrors = null; let errors = 0; @@ -70110,14 +70167,14 @@ vErrors.push(err15); } errors++; } -validate184.errors = vErrors; +validate185.errors = vErrors; return errors === 0; } -export const TerminalDetachedParams = validate185; -const schema186 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":false}; +export const TerminalDetachedParams = validate186; +const schema187 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":false}; -function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalDetachedParams" */; let vErrors = null; let errors = 0; @@ -70167,14 +70224,14 @@ vErrors.push(err3); } errors++; } -validate185.errors = vErrors; +validate186.errors = vErrors; return errors === 0; } -export const TerminalExitedParams = validate186; -const schema187 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":false}; +export const TerminalExitedParams = validate187; +const schema188 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":false}; -function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalExitedParams" */; let vErrors = null; let errors = 0; @@ -70259,14 +70316,14 @@ vErrors.push(err6); } errors++; } -validate186.errors = vErrors; +validate187.errors = vErrors; return errors === 0; } -export const TerminalIDParams = validate187; -const schema188 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":false}; +export const TerminalIDParams = validate188; +const schema189 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":false}; -function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalIDParams" */; let vErrors = null; let errors = 0; @@ -70316,14 +70373,14 @@ vErrors.push(err3); } errors++; } -validate187.errors = vErrors; +validate188.errors = vErrors; return errors === 0; } -export const TerminalInputParams = validate188; -const schema189 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":false}; +export const TerminalInputParams = validate189; +const schema190 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":false}; -function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalInputParams" */; let vErrors = null; let errors = 0; @@ -70375,7 +70432,7 @@ errors++; if(data.bytes !== undefined){ let data1 = data.bytes; if((typeof data1 !== "string") && (data1 !== null)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema189.properties.bytes.type},message:"must be string,null"}; +const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema190.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err4]; } @@ -70408,14 +70465,14 @@ vErrors.push(err6); } errors++; } -validate188.errors = vErrors; +validate189.errors = vErrors; return errors === 0; } -export const TerminalOpenParams = validate189; -const schema190 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":false}; +export const TerminalOpenParams = validate190; +const schema191 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":false}; -function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenParams" */; let vErrors = null; let errors = 0; @@ -70513,14 +70570,14 @@ vErrors.push(err7); } errors++; } -validate189.errors = vErrors; +validate190.errors = vErrors; return errors === 0; } -export const TerminalOpenResult = validate190; -const schema191 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":false}; +export const TerminalOpenResult = validate191; +const schema192 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":false}; -function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenResult" */; let vErrors = null; let errors = 0; @@ -70614,14 +70671,14 @@ vErrors.push(err7); } errors++; } -validate190.errors = vErrors; +validate191.errors = vErrors; return errors === 0; } -export const TerminalOutputParams = validate191; -const schema192 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":false}; +export const TerminalOutputParams = validate192; +const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":false}; -function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOutputParams" */; let vErrors = null; let errors = 0; @@ -70718,7 +70775,7 @@ errors++; if(data.bytes !== undefined){ let data2 = data.bytes; if((typeof data2 !== "string") && (data2 !== null)){ -const err8 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema192.properties.bytes.type},message:"must be string,null"}; +const err8 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema193.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err8]; } @@ -70751,14 +70808,14 @@ vErrors.push(err10); } errors++; } -validate191.errors = vErrors; +validate192.errors = vErrors; return errors === 0; } -export const TerminalResizeParams = validate192; -const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":false}; +export const TerminalResizeParams = validate193; +const schema194 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":false}; -function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalResizeParams" */; let vErrors = null; let errors = 0; @@ -70854,14 +70911,14 @@ vErrors.push(err7); } errors++; } -validate192.errors = vErrors; +validate193.errors = vErrors; return errors === 0; } -export const TerminalWriteParams = validate193; -const schema194 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":false}; +export const TerminalWriteParams = validate194; +const schema195 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":false}; -function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalWriteParams" */; let vErrors = null; let errors = 0; @@ -70913,7 +70970,7 @@ errors++; if(data.bytes !== undefined){ let data1 = data.bytes; if((typeof data1 !== "string") && (data1 !== null)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema194.properties.bytes.type},message:"must be string,null"}; +const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema195.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err4]; } @@ -70946,14 +71003,14 @@ vErrors.push(err6); } errors++; } -validate193.errors = vErrors; +validate194.errors = vErrors; return errors === 0; } -export const TextParams = validate194; -const schema195 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":false}; +export const TextParams = validate195; +const schema196 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":false}; -function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TextParams" */; let vErrors = null; let errors = 0; @@ -71003,14 +71060,14 @@ vErrors.push(err3); } errors++; } -validate194.errors = vErrors; +validate195.errors = vErrors; return errors === 0; } -export const TextResult = validate195; -const schema196 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":false}; +export const TextResult = validate196; +const schema197 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":false}; -function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TextResult" */; let vErrors = null; let errors = 0; @@ -71060,14 +71117,14 @@ vErrors.push(err3); } errors++; } -validate195.errors = vErrors; +validate196.errors = vErrors; return errors === 0; } -export const TitleParams = validate196; -const schema197 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":false}; +export const TitleParams = validate197; +const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":false}; -function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TitleParams" */; let vErrors = null; let errors = 0; @@ -71117,14 +71174,14 @@ vErrors.push(err3); } errors++; } -validate196.errors = vErrors; +validate197.errors = vErrors; return errors === 0; } -export const TitleResult = validate197; -const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":false}; +export const TitleResult = validate198; +const schema199 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":false}; -function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TitleResult" */; let vErrors = null; let errors = 0; @@ -71174,14 +71231,14 @@ vErrors.push(err3); } errors++; } -validate197.errors = vErrors; +validate198.errors = vErrors; return errors === 0; } -export const ToolCallParams = validate198; -const schema199 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":false}; +export const ToolCallParams = validate199; +const schema200 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":false}; -function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolCallParams" */; let vErrors = null; let errors = 0; @@ -71241,14 +71298,14 @@ vErrors.push(err4); } errors++; } -validate198.errors = vErrors; +validate199.errors = vErrors; return errors === 0; } -export const ToolCancelParams = validate199; -const schema200 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":false}; +export const ToolCancelParams = validate200; +const schema201 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":false}; -function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolCancelParams" */; let vErrors = null; let errors = 0; @@ -71365,14 +71422,14 @@ vErrors.push(err9); } errors++; } -validate199.errors = vErrors; +validate200.errors = vErrors; return errors === 0; } -export const ToolConfigureParams = validate200; -const schema201 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":false}; +export const ToolConfigureParams = validate201; +const schema202 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":false}; -function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolConfigureParams" */; let vErrors = null; let errors = 0; @@ -71422,14 +71479,14 @@ vErrors.push(err3); } errors++; } -validate200.errors = vErrors; +validate201.errors = vErrors; return errors === 0; } -export const ToolInvokeParams = validate201; -const schema202 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":false}; +export const ToolInvokeParams = validate202; +const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":false}; -function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolInvokeParams" */; let vErrors = null; let errors = 0; @@ -71535,7 +71592,7 @@ vErrors.push(err9); errors++; } for(const key0 in data){ -if(!(func2.call(schema202.properties, key0))){ +if(!(func2.call(schema203.properties, key0))){ const err10 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; if(vErrors === null){ vErrors = [err10]; @@ -71711,14 +71768,14 @@ vErrors.push(err24); } errors++; } -validate201.errors = vErrors; +validate202.errors = vErrors; return errors === 0; } -export const ToolProgressParams = validate202; -const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":false}; +export const ToolProgressParams = validate203; +const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":false}; -function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolProgressParams" */; let vErrors = null; let errors = 0; @@ -71835,14 +71892,14 @@ vErrors.push(err9); } errors++; } -validate202.errors = vErrors; +validate203.errors = vErrors; return errors === 0; } -export const ToolResultParams = validate203; -const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":false}; +export const ToolResultParams = validate204; +const schema205 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":false}; -function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolResultParams" */; let vErrors = null; let errors = 0; @@ -71949,19 +72006,19 @@ vErrors.push(err8); } errors++; } -validate203.errors = vErrors; +validate204.errors = vErrors; return errors === 0; } -export const ToolSchemaResult = validate204; -const schema205 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":false}},"required":["type","function"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; +export const ToolSchemaResult = validate205; +const schema206 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":false}},"required":["type","function"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; -function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolSchemaResult" */; let vErrors = null; let errors = 0; if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema205.type},message:"must be null,array"}; +const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema206.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err0]; } @@ -72113,14 +72170,14 @@ errors++; } } } -validate204.errors = vErrors; +validate205.errors = vErrors; return errors === 0; } -export const TraceExportParams = validate205; -const schema206 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":false}; +export const TraceExportParams = validate206; +const schema207 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":false}; -function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TraceExportParams" */; let vErrors = null; let errors = 0; @@ -72182,14 +72239,14 @@ vErrors.push(err4); } errors++; } -validate205.errors = vErrors; +validate206.errors = vErrors; return errors === 0; } -export const TraceExportResult = validate206; -const schema207 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":false}; +export const TraceExportResult = validate207; +const schema208 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":false}; -function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TraceExportResult" */; let vErrors = null; let errors = 0; @@ -72413,14 +72470,14 @@ vErrors.push(err18); } errors++; } -validate206.errors = vErrors; +validate207.errors = vErrors; return errors === 0; } -export const TracePageParams = validate207; -const schema208 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":false}; +export const TracePageParams = validate208; +const schema209 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":false}; -function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TracePageParams" */; let vErrors = null; let errors = 0; @@ -72542,14 +72599,14 @@ vErrors.push(err9); } errors++; } -validate207.errors = vErrors; +validate208.errors = vErrors; return errors === 0; } -export const UnsubscribeParams = validate208; -const schema209 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":false}; +export const UnsubscribeParams = validate209; +const schema210 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":false}; -function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UnsubscribeParams" */; let vErrors = null; let errors = 0; @@ -72599,14 +72656,14 @@ vErrors.push(err3); } errors++; } -validate208.errors = vErrors; +validate209.errors = vErrors; return errors === 0; } -export const UploadBeginParams = validate209; -const schema210 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":false}; +export const UploadBeginParams = validate210; +const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":false}; -function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadBeginParams" */; let vErrors = null; let errors = 0; @@ -72781,14 +72838,14 @@ vErrors.push(err14); } errors++; } -validate209.errors = vErrors; +validate210.errors = vErrors; return errors === 0; } -export const UploadChunkParams = validate210; -const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":false}; +export const UploadChunkParams = validate211; +const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":false}; -function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadChunkParams" */; let vErrors = null; let errors = 0; @@ -72885,7 +72942,7 @@ errors++; if(data.data !== undefined){ let data2 = data.data; if((typeof data2 !== "string") && (data2 !== null)){ -const err8 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema211.properties.data.type},message:"must be string,null"}; +const err8 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema212.properties.data.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err8]; } @@ -72918,14 +72975,14 @@ vErrors.push(err10); } errors++; } -validate210.errors = vErrors; +validate211.errors = vErrors; return errors === 0; } -export const UploadFinishParams = validate211; -const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":false}; +export const UploadFinishParams = validate212; +const schema213 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":false}; -function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadFinishParams" */; let vErrors = null; let errors = 0; @@ -72975,19 +73032,19 @@ vErrors.push(err3); } errors++; } -validate211.errors = vErrors; +validate212.errors = vErrors; return errors === 0; } -export const UserHistoryResult = validate212; -const schema213 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; +export const UserHistoryResult = validate213; +const schema214 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; -function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate213(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UserHistoryResult" */; let vErrors = null; let errors = 0; if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema213.type},message:"must be null,array"}; +const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema214.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err0]; } @@ -73011,6 +73068,6 @@ errors++; } } } -validate212.errors = vErrors; +validate213.errors = vErrors; return errors === 0; } diff --git a/packages/protocol/generated/response-validators.js b/packages/protocol/generated/response-validators.js index 59709f686..975b8599a 100644 --- a/packages/protocol/generated/response-validators.js +++ b/packages/protocol/generated/response-validators.js @@ -60963,10 +60963,55 @@ validate172.errors = vErrors; return errors === 0; } -export const SessionUpdateEvent = validate173; -const schema174 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":true}; +export const SessionTitleChangedParams = validate173; +const schema174 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionTitleChangedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionTitleChangedParams","required":["root_id"],"additionalProperties":true}; function validate173(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +/*# sourceURL="https://whip.dev/protocol/v6/SessionTitleChangedParams" */; +let vErrors = null; +let errors = 0; +if(data && typeof data == "object" && !Array.isArray(data)){ +if(data.root_id === undefined){ +const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; +if(vErrors === null){ +vErrors = [err0]; +} +else { +vErrors.push(err0); +} +errors++; +} +if(data.root_id !== undefined){ +if(typeof data.root_id !== "string"){ +const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; +if(vErrors === null){ +vErrors = [err1]; +} +else { +vErrors.push(err1); +} +errors++; +} +} +} +else { +const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; +if(vErrors === null){ +vErrors = [err2]; +} +else { +vErrors.push(err2); +} +errors++; +} +validate173.errors = vErrors; +return errors === 0; +} + +export const SessionUpdateEvent = validate174; +const schema175 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":true}; + +function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SessionUpdateEvent" */; let vErrors = null; let errors = 0; @@ -60974,7 +61019,7 @@ if(data && typeof data == "object" && !Array.isArray(data)){ if(data.archived !== undefined){ let data0 = data.archived; if((data0 !== null) && (typeof data0 !== "boolean")){ -const err0 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema174.properties.archived.type},message:"must be null,boolean"}; +const err0 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema175.properties.archived.type},message:"must be null,boolean"}; if(vErrors === null){ vErrors = [err0]; } @@ -61059,7 +61104,7 @@ errors++; if(data.permission_mode !== undefined){ let data7 = data.permission_mode; if((data7 !== null) && (typeof data7 !== "string")){ -const err7 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema174.properties.permission_mode.type},message:"must be null,string"}; +const err7 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema175.properties.permission_mode.type},message:"must be null,string"}; if(vErrors === null){ vErrors = [err7]; } @@ -61080,14 +61125,14 @@ vErrors.push(err8); } errors++; } -validate173.errors = vErrors; +validate174.errors = vErrors; return errors === 0; } -export const ShellParams = validate174; -const schema175 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":true}; +export const ShellParams = validate175; +const schema176 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":true}; -function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ShellParams" */; let vErrors = null; let errors = 0; @@ -61125,14 +61170,14 @@ vErrors.push(err2); } errors++; } -validate174.errors = vErrors; +validate175.errors = vErrors; return errors === 0; } -export const SnapshotParams = validate175; -const schema176 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":true}; +export const SnapshotParams = validate176; +const schema177 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":true}; -function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SnapshotParams" */; let vErrors = null; let errors = 0; @@ -61170,14 +61215,14 @@ vErrors.push(err2); } errors++; } -validate175.errors = vErrors; +validate176.errors = vErrors; return errors === 0; } -export const SpanPage = validate176; -const schema177 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":true}; +export const SpanPage = validate177; +const schema178 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":true}; -function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SpanPage" */; let vErrors = null; let errors = 0; @@ -61247,7 +61292,7 @@ errors++; if(data.spans !== undefined){ let data1 = data.spans; if((data1 !== null) && (!(Array.isArray(data1)))){ -const err6 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema177.properties.spans.type},message:"must be null,array"}; +const err6 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema178.properties.spans.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err6]; } @@ -61681,14 +61726,14 @@ vErrors.push(err43); } errors++; } -validate176.errors = vErrors; +validate177.errors = vErrors; return errors === 0; } -export const SpanRecord = validate177; -const schema178 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}; +export const SpanRecord = validate178; +const schema179 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}; -function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SpanRecord" */; let vErrors = null; let errors = 0; @@ -62017,14 +62062,14 @@ vErrors.push(err28); } errors++; } -validate177.errors = vErrors; +validate178.errors = vErrors; return errors === 0; } -export const StreamEvent = validate178; -const schema179 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true}},"required":["used","size","usage"],"additionalProperties":true},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":true}; +export const StreamEvent = validate179; +const schema180 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true}},"required":["used","size","usage"],"additionalProperties":true},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":true}; -function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/StreamEvent" */; let vErrors = null; let errors = 0; @@ -62044,7 +62089,7 @@ errors++; if(data.display !== undefined){ let data1 = data.display; if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err1 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema179.properties.display.type},message:"must be null,object"}; +const err1 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema180.properties.display.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err1]; } @@ -62119,7 +62164,7 @@ errors++; if(data.accounting !== undefined){ let data7 = data.accounting; if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err7 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema179.properties.accounting.type},message:"must be null,object"}; +const err7 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema180.properties.accounting.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err7]; } @@ -62605,7 +62650,7 @@ errors++; if(data.usage !== undefined){ let data20 = data.usage; if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err50 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema179.properties.usage.type},message:"must be null,object"}; +const err50 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema180.properties.usage.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err50]; } @@ -62709,7 +62754,7 @@ errors++; if(data23.cost !== undefined){ let data25 = data23.cost; if((data25 !== null) && (!(typeof data25 == "number"))){ -const err59 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; +const err59 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; if(vErrors === null){ vErrors = [err59]; } @@ -62748,7 +62793,7 @@ errors++; if(data23.prompt_tokens_details !== undefined){ let data28 = data23.prompt_tokens_details; if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err62 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; +const err62 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err62]; } @@ -62786,7 +62831,7 @@ errors++; if(data23.completion_tokens_details !== undefined){ let data30 = data23.completion_tokens_details; if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err65 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema179.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; +const err65 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err65]; } @@ -62966,14 +63011,14 @@ vErrors.push(err79); } errors++; } -validate178.errors = vErrors; +validate179.errors = vErrors; return errors === 0; } -export const SubmitPayload = validate179; -const schema180 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":true}; +export const SubmitPayload = validate180; +const schema181 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":true}; -function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubmitPayload" */; let vErrors = null; let errors = 0; @@ -62991,7 +63036,7 @@ errors++; if(data.design_context !== undefined){ let data0 = data.design_context; if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema180.properties.design_context.type},message:"must be null,object"}; +const err1 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema181.properties.design_context.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err1]; } @@ -63058,7 +63103,7 @@ errors++; if(data0.elements !== undefined){ let data3 = data0.elements; if((data3 !== null) && (!(Array.isArray(data3)))){ -const err7 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema180.properties.design_context.properties.elements.type},message:"must be null,array"}; +const err7 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema181.properties.design_context.properties.elements.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err7]; } @@ -63174,7 +63219,7 @@ errors++; if(data.parts !== undefined){ let data11 = data.parts; if((data11 !== null) && (!(Array.isArray(data11)))){ -const err16 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema180.properties.parts.type},message:"must be null,array"}; +const err16 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema181.properties.parts.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err16]; } @@ -63225,7 +63270,7 @@ errors++; if(data12.image_url !== undefined){ let data15 = data12.image_url; if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err20 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema180.properties.parts.items.properties.image_url.type},message:"must be null,object"}; +const err20 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema181.properties.parts.items.properties.image_url.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err20]; } @@ -63302,7 +63347,7 @@ errors++; if(data.attachments !== undefined){ let data19 = data.attachments; if((data19 !== null) && (!(Array.isArray(data19)))){ -const err26 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema180.properties.attachments.type},message:"must be null,array"}; +const err26 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema181.properties.attachments.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err26]; } @@ -63349,7 +63394,7 @@ vErrors.push(err29); errors++; } if(!((data21 === "image") || (data21 === "text"))){ -const err30 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema180.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; +const err30 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema181.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; if(vErrors === null){ vErrors = [err30]; } @@ -63524,14 +63569,14 @@ vErrors.push(err44); } errors++; } -validate179.errors = vErrors; +validate180.errors = vErrors; return errors === 0; } -export const SubscribeParams = validate180; -const schema181 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":true}; +export const SubscribeParams = validate181; +const schema182 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":true}; -function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscribeParams" */; let vErrors = null; let errors = 0; @@ -63636,14 +63681,14 @@ vErrors.push(err8); } errors++; } -validate180.errors = vErrors; +validate181.errors = vErrors; return errors === 0; } -export const SubscribeResult = validate181; -const schema182 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":true}; +export const SubscribeResult = validate182; +const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":true}; -function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscribeResult" */; let vErrors = null; let errors = 0; @@ -63726,14 +63771,14 @@ vErrors.push(err6); } errors++; } -validate181.errors = vErrors; +validate182.errors = vErrors; return errors === 0; } -export const SubscriptionFailure = validate182; -const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":true},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":true}; +export const SubscriptionFailure = validate183; +const schema184 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":true},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":true}; -function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/SubscriptionFailure" */; let vErrors = null; let errors = 0; @@ -63795,7 +63840,7 @@ errors++; if(data.error !== undefined){ let data2 = data.error; if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err5 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema183.properties.error.type},message:"must be null,object"}; +const err5 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema184.properties.error.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err5]; } @@ -63828,7 +63873,7 @@ errors++; if(data2.data !== undefined){ let data3 = data2.data; if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema183.properties.error.properties.data.type},message:"must be null,object"}; +const err8 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema184.properties.error.properties.data.type},message:"must be null,object"}; if(vErrors === null){ vErrors = [err8]; } @@ -63900,14 +63945,14 @@ vErrors.push(err13); } errors++; } -validate182.errors = vErrors; +validate183.errors = vErrors; return errors === 0; } -export const TerminalAttachParams = validate183; -const schema184 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":true}; +export const TerminalAttachParams = validate184; +const schema185 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":true}; -function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachParams" */; let vErrors = null; let errors = 0; @@ -63990,14 +64035,14 @@ vErrors.push(err6); } errors++; } -validate183.errors = vErrors; +validate184.errors = vErrors; return errors === 0; } -export const TerminalAttachResult = validate184; -const schema185 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":true}; +export const TerminalAttachResult = validate185; +const schema186 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":true}; -function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachResult" */; let vErrors = null; let errors = 0; @@ -64173,14 +64218,14 @@ vErrors.push(err14); } errors++; } -validate184.errors = vErrors; +validate185.errors = vErrors; return errors === 0; } -export const TerminalDetachedParams = validate185; -const schema186 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":true}; +export const TerminalDetachedParams = validate186; +const schema187 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":true}; -function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalDetachedParams" */; let vErrors = null; let errors = 0; @@ -64218,14 +64263,14 @@ vErrors.push(err2); } errors++; } -validate185.errors = vErrors; +validate186.errors = vErrors; return errors === 0; } -export const TerminalExitedParams = validate186; -const schema187 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":true}; +export const TerminalExitedParams = validate187; +const schema188 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":true}; -function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalExitedParams" */; let vErrors = null; let errors = 0; @@ -64298,14 +64343,14 @@ vErrors.push(err5); } errors++; } -validate186.errors = vErrors; +validate187.errors = vErrors; return errors === 0; } -export const TerminalIDParams = validate187; -const schema188 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":true}; +export const TerminalIDParams = validate188; +const schema189 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":true}; -function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalIDParams" */; let vErrors = null; let errors = 0; @@ -64343,14 +64388,14 @@ vErrors.push(err2); } errors++; } -validate187.errors = vErrors; +validate188.errors = vErrors; return errors === 0; } -export const TerminalInputParams = validate188; -const schema189 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":true}; +export const TerminalInputParams = validate189; +const schema190 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":true}; -function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalInputParams" */; let vErrors = null; let errors = 0; @@ -64390,7 +64435,7 @@ errors++; if(data.bytes !== undefined){ let data1 = data.bytes; if((typeof data1 !== "string") && (data1 !== null)){ -const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema189.properties.bytes.type},message:"must be string,null"}; +const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema190.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err3]; } @@ -64423,14 +64468,14 @@ vErrors.push(err5); } errors++; } -validate188.errors = vErrors; +validate189.errors = vErrors; return errors === 0; } -export const TerminalOpenParams = validate189; -const schema190 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":true}; +export const TerminalOpenParams = validate190; +const schema191 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":true}; -function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenParams" */; let vErrors = null; let errors = 0; @@ -64516,14 +64561,14 @@ vErrors.push(err6); } errors++; } -validate189.errors = vErrors; +validate190.errors = vErrors; return errors === 0; } -export const TerminalOpenResult = validate190; -const schema191 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":true}; +export const TerminalOpenResult = validate191; +const schema192 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":true}; -function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenResult" */; let vErrors = null; let errors = 0; @@ -64605,14 +64650,14 @@ vErrors.push(err6); } errors++; } -validate190.errors = vErrors; +validate191.errors = vErrors; return errors === 0; } -export const TerminalOutputParams = validate191; -const schema192 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":true}; +export const TerminalOutputParams = validate192; +const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":true}; -function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalOutputParams" */; let vErrors = null; let errors = 0; @@ -64697,7 +64742,7 @@ errors++; if(data.bytes !== undefined){ let data2 = data.bytes; if((typeof data2 !== "string") && (data2 !== null)){ -const err7 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema192.properties.bytes.type},message:"must be string,null"}; +const err7 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema193.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err7]; } @@ -64730,14 +64775,14 @@ vErrors.push(err9); } errors++; } -validate191.errors = vErrors; +validate192.errors = vErrors; return errors === 0; } -export const TerminalResizeParams = validate192; -const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":true}; +export const TerminalResizeParams = validate193; +const schema194 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":true}; -function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalResizeParams" */; let vErrors = null; let errors = 0; @@ -64821,14 +64866,14 @@ vErrors.push(err6); } errors++; } -validate192.errors = vErrors; +validate193.errors = vErrors; return errors === 0; } -export const TerminalWriteParams = validate193; -const schema194 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":true}; +export const TerminalWriteParams = validate194; +const schema195 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":true}; -function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TerminalWriteParams" */; let vErrors = null; let errors = 0; @@ -64868,7 +64913,7 @@ errors++; if(data.bytes !== undefined){ let data1 = data.bytes; if((typeof data1 !== "string") && (data1 !== null)){ -const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema194.properties.bytes.type},message:"must be string,null"}; +const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema195.properties.bytes.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err3]; } @@ -64901,14 +64946,14 @@ vErrors.push(err5); } errors++; } -validate193.errors = vErrors; +validate194.errors = vErrors; return errors === 0; } -export const TextParams = validate194; -const schema195 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":true}; +export const TextParams = validate195; +const schema196 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":true}; -function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TextParams" */; let vErrors = null; let errors = 0; @@ -64946,14 +64991,14 @@ vErrors.push(err2); } errors++; } -validate194.errors = vErrors; +validate195.errors = vErrors; return errors === 0; } -export const TextResult = validate195; -const schema196 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":true}; +export const TextResult = validate196; +const schema197 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":true}; -function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TextResult" */; let vErrors = null; let errors = 0; @@ -64991,14 +65036,14 @@ vErrors.push(err2); } errors++; } -validate195.errors = vErrors; +validate196.errors = vErrors; return errors === 0; } -export const TitleParams = validate196; -const schema197 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":true}; +export const TitleParams = validate197; +const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":true}; -function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TitleParams" */; let vErrors = null; let errors = 0; @@ -65036,14 +65081,14 @@ vErrors.push(err2); } errors++; } -validate196.errors = vErrors; +validate197.errors = vErrors; return errors === 0; } -export const TitleResult = validate197; -const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":true}; +export const TitleResult = validate198; +const schema199 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":true}; -function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TitleResult" */; let vErrors = null; let errors = 0; @@ -65081,14 +65126,14 @@ vErrors.push(err2); } errors++; } -validate197.errors = vErrors; +validate198.errors = vErrors; return errors === 0; } -export const ToolCallParams = validate198; -const schema199 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":true}; +export const ToolCallParams = validate199; +const schema200 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":true}; -function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolCallParams" */; let vErrors = null; let errors = 0; @@ -65136,14 +65181,14 @@ vErrors.push(err3); } errors++; } -validate198.errors = vErrors; +validate199.errors = vErrors; return errors === 0; } -export const ToolCancelParams = validate199; -const schema200 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":true}; +export const ToolCancelParams = validate200; +const schema201 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":true}; -function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolCancelParams" */; let vErrors = null; let errors = 0; @@ -65248,14 +65293,14 @@ vErrors.push(err8); } errors++; } -validate199.errors = vErrors; +validate200.errors = vErrors; return errors === 0; } -export const ToolConfigureParams = validate200; -const schema201 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":true}; +export const ToolConfigureParams = validate201; +const schema202 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":true}; -function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolConfigureParams" */; let vErrors = null; let errors = 0; @@ -65293,14 +65338,14 @@ vErrors.push(err2); } errors++; } -validate200.errors = vErrors; +validate201.errors = vErrors; return errors === 0; } -export const ToolInvokeParams = validate201; -const schema202 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":true}; +export const ToolInvokeParams = validate202; +const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":true}; -function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolInvokeParams" */; let vErrors = null; let errors = 0; @@ -65570,14 +65615,14 @@ vErrors.push(err23); } errors++; } -validate201.errors = vErrors; +validate202.errors = vErrors; return errors === 0; } -export const ToolProgressParams = validate202; -const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":true}; +export const ToolProgressParams = validate203; +const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":true}; -function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolProgressParams" */; let vErrors = null; let errors = 0; @@ -65682,14 +65727,14 @@ vErrors.push(err8); } errors++; } -validate202.errors = vErrors; +validate203.errors = vErrors; return errors === 0; } -export const ToolResultParams = validate203; -const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":true}; +export const ToolResultParams = validate204; +const schema205 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":true}; -function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolResultParams" */; let vErrors = null; let errors = 0; @@ -65784,19 +65829,19 @@ vErrors.push(err7); } errors++; } -validate203.errors = vErrors; +validate204.errors = vErrors; return errors === 0; } -export const ToolSchemaResult = validate204; -const schema205 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":true}},"required":["type","function"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; +export const ToolSchemaResult = validate205; +const schema206 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":true}},"required":["type","function"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; -function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/ToolSchemaResult" */; let vErrors = null; let errors = 0; if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema205.type},message:"must be null,array"}; +const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema206.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err0]; } @@ -65924,14 +65969,14 @@ errors++; } } } -validate204.errors = vErrors; +validate205.errors = vErrors; return errors === 0; } -export const TraceExportParams = validate205; -const schema206 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":true}; +export const TraceExportParams = validate206; +const schema207 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":true}; -function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TraceExportParams" */; let vErrors = null; let errors = 0; @@ -65981,14 +66026,14 @@ vErrors.push(err3); } errors++; } -validate205.errors = vErrors; +validate206.errors = vErrors; return errors === 0; } -export const TraceExportResult = validate206; -const schema207 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":true}; +export const TraceExportResult = validate207; +const schema208 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":true}; -function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TraceExportResult" */; let vErrors = null; let errors = 0; @@ -66188,14 +66233,14 @@ vErrors.push(err16); } errors++; } -validate206.errors = vErrors; +validate207.errors = vErrors; return errors === 0; } -export const TracePageParams = validate207; -const schema208 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":true}; +export const TracePageParams = validate208; +const schema209 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":true}; -function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/TracePageParams" */; let vErrors = null; let errors = 0; @@ -66305,14 +66350,14 @@ vErrors.push(err8); } errors++; } -validate207.errors = vErrors; +validate208.errors = vErrors; return errors === 0; } -export const UnsubscribeParams = validate208; -const schema209 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":true}; +export const UnsubscribeParams = validate209; +const schema210 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":true}; -function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UnsubscribeParams" */; let vErrors = null; let errors = 0; @@ -66350,14 +66395,14 @@ vErrors.push(err2); } errors++; } -validate208.errors = vErrors; +validate209.errors = vErrors; return errors === 0; } -export const UploadBeginParams = validate209; -const schema210 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":true}; +export const UploadBeginParams = validate210; +const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":true}; -function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadBeginParams" */; let vErrors = null; let errors = 0; @@ -66520,14 +66565,14 @@ vErrors.push(err13); } errors++; } -validate209.errors = vErrors; +validate210.errors = vErrors; return errors === 0; } -export const UploadChunkParams = validate210; -const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":true}; +export const UploadChunkParams = validate211; +const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":true}; -function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadChunkParams" */; let vErrors = null; let errors = 0; @@ -66612,7 +66657,7 @@ errors++; if(data.data !== undefined){ let data2 = data.data; if((typeof data2 !== "string") && (data2 !== null)){ -const err7 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema211.properties.data.type},message:"must be string,null"}; +const err7 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema212.properties.data.type},message:"must be string,null"}; if(vErrors === null){ vErrors = [err7]; } @@ -66645,14 +66690,14 @@ vErrors.push(err9); } errors++; } -validate210.errors = vErrors; +validate211.errors = vErrors; return errors === 0; } -export const UploadFinishParams = validate211; -const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":true}; +export const UploadFinishParams = validate212; +const schema213 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":true}; -function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UploadFinishParams" */; let vErrors = null; let errors = 0; @@ -66690,19 +66735,19 @@ vErrors.push(err2); } errors++; } -validate211.errors = vErrors; +validate212.errors = vErrors; return errors === 0; } -export const UserHistoryResult = validate212; -const schema213 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; +export const UserHistoryResult = validate213; +const schema214 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; -function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ +function validate213(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ /*# sourceURL="https://whip.dev/protocol/v6/UserHistoryResult" */; let vErrors = null; let errors = 0; if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema213.type},message:"must be null,array"}; +const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema214.type},message:"must be null,array"}; if(vErrors === null){ vErrors = [err0]; } @@ -66726,6 +66771,6 @@ errors++; } } } -validate212.errors = vErrors; +validate213.errors = vErrors; return errors === 0; } diff --git a/packages/protocol/schema/SessionTitleChangedParams.json b/packages/protocol/schema/SessionTitleChangedParams.json new file mode 100644 index 000000000..623cc0c2a --- /dev/null +++ b/packages/protocol/schema/SessionTitleChangedParams.json @@ -0,0 +1,15 @@ +{ + "type": "object", + "properties": { + "root_id": { + "type": "string" + } + }, + "$id": "https://whip.dev/protocol/v6/SessionTitleChangedParams", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "SessionTitleChangedParams", + "required": [ + "root_id" + ], + "additionalProperties": false +} diff --git a/packages/protocol/schema/manifest.json b/packages/protocol/schema/manifest.json index 87e09e6b7..b93ae2797 100644 --- a/packages/protocol/schema/manifest.json +++ b/packages/protocol/schema/manifest.json @@ -1002,14 +1002,6 @@ "params_type": "ArchiveParams", "result_type": "ArchiveResult" }, - { - "name": "session.autotitle", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "Empty" - }, { "name": "session.create", "surface": "runtime", @@ -1188,6 +1180,7 @@ "event": "EventNotification", "hook.cancel": "ToolCancelParams", "hook.invoke": "HookInvokeParams", + "sessions.title.changed": "SessionTitleChangedParams", "subscription.failed": "SubscriptionFailure", "terminal.detached": "TerminalDetachedParams", "terminal.exited": "TerminalExitedParams", diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts index a2a4b914e..80514900c 100644 --- a/packages/sdk/src/client.ts +++ b/packages/sdk/src/client.ts @@ -4,7 +4,7 @@ import { type InitializeResult, type QueryOperation, type QueryResult, type RootEvent, type RpcMethod, type RpcMethods, type RuntimeOperation, type RuntimeOperations, type HookInvokeParams, type ToolCancelParams, type ToolInvokeParams, - type TerminalDetachedParams, type TerminalExitedParams, type TerminalOutputParams, + type TerminalDetachedParams, type TerminalExitedParams, type TerminalOutputParams, type SessionTitleChangedParams, type BrowserInventoryRequest, type BrowserCommand, type BrowserCommandCancel, type BrowserProviderRevoked, } from '@whip/protocol'; import { CommandHandle, type CommandOptions, type RecoveryRecord, type RecoveryStorage, type CommandOutcome } from './command.js'; @@ -20,8 +20,9 @@ import { webSocket, type Transport, type TransportFactory } from './transport.js import { byteLength, frozen, notify, object, withSignal, uuid, digestHex } from './util.js'; export type SdkEvent = RootEvent; -/** Notifications the daemon addresses to one connection: executor leases and terminal attachments. */ +/** Typed notifications the daemon addresses to this connection. */ export interface Notifications { + 'sessions.title.changed': SessionTitleChangedParams; 'browser.inventory': BrowserInventoryRequest; 'browser.command': BrowserCommand; 'browser.command.cancel': BrowserCommandCancel; 'browser.provider.revoked': BrowserProviderRevoked; @@ -186,7 +187,7 @@ export class WhipClient { this.connection = connection; const info = await this.dispatch('initialize', { protocol_major: manifest.major, client_id: this.clientId, client_kind: this.clientKind, - build_id: this.options.buildId ?? '@whip/sdk', capabilities: ['commands', 'events', 'snapshots', 'uploads', 'history_pages', 'collections', 'host_configuration', 'workspace_completion', 'host_skill_completion', 'host_global_skill_completion', 'skill_catalog_completion', 'host_views', 'themes', 'mailbox_inspection', 'input_attachments', 'session_summaries', 'execution_engines', ...(this.options.browserProvider ? ['desktop-browser-v1', 'desktop-browser-v2'] : [])], + build_id: this.options.buildId ?? '@whip/sdk', capabilities: ['commands', 'events', 'snapshots', 'uploads', 'history_pages', 'collections', 'host_configuration', 'workspace_completion', 'host_skill_completion', 'host_global_skill_completion', 'skill_catalog_completion', 'host_views', 'themes', 'mailbox_inspection', 'input_attachments', 'session_summaries', 'session_title_notifications', 'execution_engines', ...(this.options.browserProvider ? ['desktop-browser-v1', 'desktop-browser-v2'] : [])], }, { signal: controller.signal }, true); if (epoch !== this.epoch || this.closed || controller.signal.aborted) throw abortError(controller.signal); if (info.protocol_major !== manifest.major) throw new WhipError('unsupported_protocol', 'Daemon protocol major is incompatible'); diff --git a/packages/sdk/src/state.ts b/packages/sdk/src/state.ts index 9caefa84f..1e4b7a450 100644 --- a/packages/sdk/src/state.ts +++ b/packages/sdk/src/state.ts @@ -897,10 +897,13 @@ export class SessionListView { private timer?: ReturnType; private stopConnection?: () => void; private stopCommands?: () => void; + private stopTitles?: () => void; private pending?: Promise; private started = false; private epoch = 0; private refreshAgain = false; + // ponytail: Map preserves insertion order, so re-insertion lands at the end. + private readonly overlays = new Map[number]; index: number }>(); private runtimeID?: string; private readonly interval: number; private readonly maxBytes: number; @@ -941,6 +944,9 @@ export class SessionListView { this.stopCommands = this.client.onCommand(terminalChanges(() => { if (this.listeners.size) void this.refresh(); })); + this.stopTitles = this.client.onNotification('sessions.title.changed', () => { + if (this.listeners.size) void this.refresh(); + }); await this.refresh(); this.pollLater(); } @@ -960,7 +966,10 @@ export class SessionListView { if (!this.current.page?.has_more) return; if (!this.current.page.next_cursor) throw new WhipError('invalid_response', 'Session list is missing its continuation cursor'); this.pending = this.fetch(true); - try { await this.pending; } finally { this.pending = undefined; } + try { await this.pending; } finally { + this.pending = undefined; + if (this.refreshAgain) { this.refreshAgain = false; void this.refresh(); } + } } async dispose(): Promise { @@ -970,10 +979,26 @@ export class SessionListView { clearTimeout(this.timer); this.stopConnection?.(); this.stopCommands?.(); + this.stopTitles?.(); this.set({ ...this.current, status: 'closed' }); this.listeners.clear(); } + /** Hide or restore an item before the host confirms; the next refresh reconciles. */ + setOptimisticArchived(rootId: string, archived: boolean): void { + const items = this.current.page?.items; + const index = items?.findIndex(item => item.id === rootId) ?? -1; + if (index >= 0) { + if (archived) this.overlays.set(rootId, { archived, item: items![index]!, index }); + else this.overlays.delete(rootId); + } else { + const entry = this.overlays.get(rootId); + if (archived) this.overlays.delete(rootId); + else this.overlays.set(rootId, { ...entry, archived, index: entry?.index ?? -1 }); + } + if (this.current.page) this.publish(this.current.page); + } + private async fetch(more: boolean): Promise { const epoch = this.epoch; const previous = this.current.page; @@ -993,7 +1018,7 @@ export class SessionListView { const merged = { ...page, items: more ? [...(previous?.items ?? []), ...(page.items ?? [])] : page.items }; if (bytes(merged) > this.maxBytes) { this.set({ ...this.current, status: 'live', truncated: true, error: new Error('Session list cache is full; refresh to start a new page window') }); - } else this.set({ status: 'live', page: merged, truncated: false }); + } else this.publish(merged); } catch (error) { if (epoch !== this.epoch || this.lifetime.signal.aborted) return; this.set({ ...this.current, status: previous ? 'stale' : 'error', error: asError(error) }); @@ -1017,6 +1042,23 @@ export class SessionListView { this.current = freeze(value) as SessionListSnapshot; for (const listener of this.listeners) listener(); } + + private publish(page: SessionCatalogPage): void { + let items = page.items; + if (this.overlays.size && items) { + items = [...items]; + for (const [id, entry] of this.overlays) { + const index = items.findIndex(item => item.id === id); + if (entry.archived) { + if (index >= 0) entry.item = items[index]; else this.overlays.delete(id); + if (index >= 0) items.splice(index, 1); + } else if (index >= 0) this.overlays.delete(id); + else if (entry.item) items.splice(Math.min(entry.index < 0 ? items.length : entry.index, items.length), 0, entry.item); + else this.overlays.delete(id); + } + } + this.set({ status: 'live', page: { ...page, items }, truncated: false }); + } } export function createSessionListView(client: WhipClient, options?: { pollIntervalMs?: number; maxBytes?: number }): SessionListView { diff --git a/packages/sdk/test/client.test.ts b/packages/sdk/test/client.test.ts index 20d0fcb04..86d97b802 100644 --- a/packages/sdk/test/client.test.ts +++ b/packages/sdk/test/client.test.ts @@ -615,6 +615,42 @@ test('pausing from a connection subscriber cannot leave a heartbeat scheduled', assert.equal(server.connections.length, 1); }); +test('title notifications negotiate support, validate the wire payload, and survive reconnect without root streams', async t => { + const fixture = harness((request, connection) => { + if (request.method !== 'initialize') throw new Error('Unexpected request: ' + request.method); + assert.ok((request.params.capabilities as string[]).includes('session_title_notifications')); + connection.reply(request, { ...initialize(), capabilities: ['session_title_notifications'], negotiated_capabilities: ['session_title_notifications'] }); + }); + const client = new WhipClient({ endpoint: fixture.factory, clientId: 'client' }); + t.after(() => client.close()); + const titles: string[] = []; + const off = client.onNotification('sessions.title.changed', params => titles.push(params.root_id)); + await client.connect(); + fixture.connections[0]!.notify('sessions.title.changed', { root_id: 'unopened' }); + assert.deepEqual(titles, ['unopened']); + fixture.connections[0]!.fail(); + await client.connect(); assert.equal(fixture.connections.length, 2); + fixture.connections[1]!.notify('sessions.title.changed', { root_id: 'other' }); + assert.deepEqual(titles, ['unopened', 'other']); + off(); + fixture.connections[1]!.notify('sessions.title.changed', { root_id: 'ignored' }); + assert.equal(titles.length, 2); + assert.ok(fixture.connections.every(connection => connection.requests.every(request => request.method === 'initialize'))); + fixture.connections[1]!.notify('sessions.title.changed', { root_id: 42 }); + assert.notEqual(client.getSnapshot().state, 'connected'); +}); + +test('new SDK connects to an older host without title notification support', async t => { + const fixture = harness(); + const client = new WhipClient({ endpoint: fixture.factory, clientId: 'client' }); + t.after(() => client.close()); + const off = client.onNotification('sessions.title.changed', () => assert.fail('No title notifications from an older host')); + await client.connect(); + assert.equal(client.getSnapshot().state, 'connected'); + assert.deepEqual(client.getSnapshot().info?.negotiated_capabilities, []); + off(); +}); + test('initialization requests host and catalog skill capabilities and preserves negotiated support', async t => { const skills = ['workspace_completion', 'host_skill_completion', 'host_global_skill_completion', 'skill_catalog_completion']; const server = harness((request, connection) => { diff --git a/packages/sdk/test/state.test.ts b/packages/sdk/test/state.test.ts index ad6928808..ebd49a1ee 100644 --- a/packages/sdk/test/state.test.ts +++ b/packages/sdk/test/state.test.ts @@ -58,6 +58,12 @@ class Host { streams: Stream[] = []; listeners = new Set<() => void>(); commands = new Set<(outcome: { command_id: string; status: string }) => void>(); + titles = new Set<(params: { root_id: string }) => void>(); + onNotification = (method: string, fn: (params: { root_id: string }) => void) => { + assert.equal(method, 'sessions.title.changed'); + this.titles.add(fn); return () => { this.titles.delete(fn); }; + }; + titleChanged(root_id = 'root') { for (const listener of this.titles) listener({ root_id }); } calls: { method: string; params: Record }[] = []; connection = { state: 'connected', info: { runtime_id: 'runtime', connection_id: 'connection-1' } }; history?: (params: Record, options?: CallOptions) => Promise; @@ -1037,29 +1043,174 @@ test('questions resolve across clients and unknown event payloads stay explicit' await view.dispose(); }); -test('catalog polling is observed, revision-based, and never opens roots', async () => { +test('catalog polling updates an unopened session title without a root subscription', async t => { const host = new Host(); + host.catalogItems = [{ ...host.catalogItems[0]!, title: '' }]; const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 10 }); + t.after(() => list.dispose()); await list.start(); const initial = host.calls.length; await pause(25); assert.equal(host.calls.length, initial); const stop = list.subscribe(() => {}); await until(() => host.calls.some(call => call.method === 'sessions.revision')); - host.catalogRevision = '2'; - host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Renamed' }]; - await until(() => list.getSnapshot().page?.revision === '2'); - assert.equal(list.getSnapshot().page?.items?.[0]?.title, 'Renamed'); + // Another client accepts the first message, then background naming completes. + // This observer receives only persisted catalog revisions, not root events. + for (const [revision, title] of [['2', 'Help me repair the build'], ['3', 'Repair build']] as const) { + host.catalogRevision = revision; + host.catalogItems = [{ ...host.catalogItems[0]!, title }]; + await until(() => list.getSnapshot().page?.revision === revision); + assert.equal(list.getSnapshot().page?.items?.[0]?.title, title); + } stop(); await pause(15); const stopped = host.calls.length; + host.catalogRevision = '4'; + host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Manually renamed' }]; await pause(25); assert.equal(host.calls.length, stopped); + const observeAgain = list.subscribe(() => {}); + await until(() => list.getSnapshot().page?.items?.[0]?.title === 'Manually renamed'); + observeAgain(); assert.equal(host.streams.length, 0); assert.ok(host.calls.every(call => call.method.startsWith('sessions.'))); await list.dispose(); }); +test('a title changed during an in-flight catalog poll converges on the next poll', async t => { + const host = new Host(); + const call = host.call.bind(host); + let release: (() => void) | undefined; + let delayed = false; + t.mock.method(host, 'call', async (method: string, params: Record, options?: CallOptions) => { + const result = await call(method, params, options); + if (method === 'sessions.revision' && !delayed) { + delayed = true; + await new Promise(resolve => { release = resolve; }); + } + return result; + }); + const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 10 }); + const stop = list.subscribe(() => {}); + t.after(async () => { release?.(); stop(); await list.dispose(); }); + await list.start(); + await until(() => !!release); + host.catalogRevision = '2'; + host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Generated during poll' }]; + release!(); + await until(() => list.getSnapshot().page?.items?.[0]?.title === 'Generated during poll'); + assert.equal(list.getSnapshot().page?.revision, '2'); + assert.equal(host.streams.length, 0); + assert.ok(host.calls.every(call => call.method.startsWith('sessions.'))); +}); + +test('title hints refresh unopened catalogs, including off-page roots, without disturbing observation or overlays', async t => { + const host = new Host(); + const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 60_000 }); + let stop = list.subscribe(() => {}); + t.after(async () => { stop(); await list.dispose(); }); + await list.start(); await list.start(); + assert.equal(host.titles.size, 1); + list.setOptimisticArchived('root', true); + host.catalogRevision = '2'; + host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Changed on another client' }, { ...host.catalogItems[0]!, id: 'new-fork', title: 'Fork title' }]; + host.titleChanged('new-fork'); + await until(() => list.getSnapshot().page?.revision === '2'); + assert.deepEqual(list.getSnapshot().page?.items?.map(item => item.title), ['Fork title']); + list.setOptimisticArchived('root', false); + assert.equal(list.getSnapshot().page?.items?.[0]?.title, 'Changed on another client'); + assert.equal(host.streams.length, 0); + stop(); + const calls = host.calls.length; + host.catalogRevision = '3'; host.titleChanged(); + await pause(5); + assert.equal(host.calls.length, calls); + stop = list.subscribe(() => {}); + await until(() => list.getSnapshot().page?.revision === '3'); + host.notify('reconnecting'); host.titleChanged(); + assert.equal(list.getSnapshot().status, 'stale'); + host.catalogRevision = '4'; host.notify('connected'); + await until(() => list.getSnapshot().page?.revision === '4'); + assert.equal(host.titles.size, 1); + await list.dispose(); + assert.equal(host.titles.size, 0); +}); + +for (const blocked of ['sessions.revision', 'sessions.list', 'loadMore']) { + test('title hints during ' + blocked + ' coalesce and reconcile after an old result', async t => { + const host = new Host(); + const call = host.call.bind(host); + let release!: () => void; + let held = false; + let hold = false; + host.call = async (method, params, options) => { + if (hold && !held && method === (blocked === 'loadMore' ? 'sessions.list' : blocked)) { + held = true; + const old = await call(method, params, options); + await new Promise(resolve => { release = resolve; }); + return old; + } + const result = await call(method, params, options); + return blocked === 'loadMore' && method === 'sessions.list' ? { ...result as object, has_more: true, next_cursor: 'next' } : result; + }; + const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 60_000 }); + const stop = list.subscribe(() => {}); + t.after(async () => { stop(); await list.dispose(); }); + await list.start(); + // Revision and pagination reads must return the old unchanged revision, so only the queued refresh can catch up. + if (blocked === 'sessions.list') host.catalogRevision = '2'; + hold = true; + const pending = blocked === 'loadMore' ? list.loadMore() : list.refresh(); + await until(() => !!release); + host.catalogRevision = '3'; host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Newest title' }]; + const before = host.calls.length; + for (let i = 0; i < 20; i++) host.titleChanged('off-page'); + assert.equal(host.calls.length, before); + release(); await pending; + await until(() => list.getSnapshot().page?.revision === '3'); + assert.equal(list.getSnapshot().page?.items?.[0]?.title, 'Newest title'); + assert.ok(host.calls.length - before <= 3); + assert.equal(host.streams.length, 0); + }); +} + +test('a title hint acknowledging an archived root keeps unrelated catalog items', async t => { + const host = new Host(); + const other = { ...host.catalogItems[0]!, id: 'other', title: 'Other session' }; + host.catalogItems.push(other); + const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 60_000 }); + const stop = list.subscribe(() => {}); + t.after(async () => { stop(); await list.dispose(); }); + await list.start(); + list.setOptimisticArchived('root', true); + host.catalogRevision = '2'; host.catalogItems = [{ ...other, title: 'Other renamed' }]; + host.titleChanged('other'); + await until(() => list.getSnapshot().page?.revision === '2'); + assert.deepEqual(list.getSnapshot().page?.items, host.catalogItems); +}); + +test('optimistic archive hides the item immediately and reconciles against the server', async t => { + const host = new Host(); + const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 60_000 }); + const stop = list.subscribe(() => {}); + t.after(async () => { stop(); await list.dispose(); }); + await list.start(); + const item = host.catalogItems[0]!; + list.setOptimisticArchived('root', true); + assert.deepEqual(list.getSnapshot().page?.items, []); + // A failed archive reverts before any refresh: the item returns in place. + list.setOptimisticArchived('root', false); + assert.deepEqual(list.getSnapshot().page?.items, [item]); + // Re-archive, then a refresh whose server truth agrees drops the overlay. + list.setOptimisticArchived('root', true); + host.catalogRevision = '2'; host.catalogItems = []; + await list.refresh(); + assert.deepEqual(list.getSnapshot().page?.items, []); + host.catalogRevision = '3'; host.catalogItems = [item]; + await list.refresh(); + assert.deepEqual(list.getSnapshot().page?.items, [item]); +}); + test('archive completion refreshes the active catalog once without waiting for the poll or opening a root', async t => { const host = new Host(); const list = createSessionListView(host as unknown as WhipClient, { pollIntervalMs: 60_000 }); @@ -1092,8 +1243,11 @@ test('an observed catalog stops its timer while paused and resumes polling on re assert.equal(refresh.mock.callCount(), 0, 'paused observers must not keep waking a timer'); assert.equal(list.getSnapshot().status, 'stale'); host.catalogRevision = '2'; + host.catalogItems = [{ ...host.catalogItems[0]!, title: 'Named while disconnected' }]; host.notify('connected'); await until(() => list.getSnapshot().page?.revision === '2'); + assert.equal(list.getSnapshot().page?.items?.[0]?.title, 'Named while disconnected'); + assert.equal(host.streams.length, 0); const resumed = refresh.mock.callCount(); await until(() => refresh.mock.callCount() > resumed); assert.equal(list.getSnapshot().status, 'live'); From c62368e1ec496d6e3466018af877548ebe671005 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sun, 27 Sep 2026 16:26:10 -0700 Subject: [PATCH 05/67] fix(session): derive the root agent's saved selection from sessions session.model, session.effort and workspace.set write model, provider, effort and cwd to the sessions row, but the root's agents row only copies those columns in EnsureRootAuthority at open. agents.inspect, root snapshots and RootAgentViews therefore reported the pre-change values until the daemon reopened the session. Read the root's selection from sessions in the two queries that can return the root row. Children keep their admitted values. The physical columns stay populated for older binaries; no schema change. Co-Authored-By: Claude Fable 5.1 --- internal/session/event.go | 4 +- internal/session/root_projection_test.go | 84 ++++++++++++++++++++++++ internal/session/swarm.go | 13 +++- 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 internal/session/root_projection_test.go diff --git a/internal/session/event.go b/internal/session/event.go index 5f001ecaf..66f6818f8 100644 --- a/internal/session/event.go +++ b/internal/session/event.go @@ -398,9 +398,9 @@ func readSnapshotMessages(ctx context.Context, tx *sql.Tx, rootID string, snapsh } func readSnapshotAgents(ctx context.Context, tx *sql.Tx, rootID string, snapshot *RootSnapshot) error { - rows, err := tx.QueryContext(ctx, `SELECT a.id,a.root_id,COALESCE(a.parent_id,''),a.name,a.model,a.provider,a.effort,a.cwd,a.report,a.status,a.last_turn, + rows, err := tx.QueryContext(ctx, `SELECT a.id,a.root_id,COALESCE(a.parent_id,''),a.name,`+rootSelectionColumns+`,a.report,a.status,a.last_turn, (SELECT count(*) FROM agent_messages m WHERE m.root_id=a.root_id AND m.recipient_agent_id=a.id AND m.status='pending') - FROM agents a WHERE a.root_id=? ORDER BY a.created_at,a.id LIMIT ?`, rootID, snapshot.collectionLimit()) + FROM agents a JOIN sessions s ON s.id=a.root_id WHERE a.root_id=? ORDER BY a.created_at,a.id LIMIT ?`, rootID, snapshot.collectionLimit()) if err != nil { return err } diff --git a/internal/session/root_projection_test.go b/internal/session/root_projection_test.go new file mode 100644 index 000000000..0f802be0c --- /dev/null +++ b/internal/session/root_projection_test.go @@ -0,0 +1,84 @@ +package session + +import ( + "path/filepath" + "testing" +) + +// The root agent's model, provider, effort and cwd are session facts that +// session.model, session.effort and workspace.set write to the sessions row. +// Every agent read must report those saved values for the root while children +// keep the selection they were admitted with. +func TestRootAgentReadsDeriveSelectionFromSession(t *testing.T) { + ctx := t.Context() + store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = store.Close() }) + rootID, err := store.Create(SessionKindAgent, t.TempDir(), "model", "provider") + if err != nil { + t.Fatal(err) + } + if _, err := store.EnsureAuthority(ctx, rootID); err != nil { + t.Fatal(err) + } + childCWD := t.TempDir() + if _, err := store.AdmitAgent(ctx, AgentAdmission{ + RootID: rootID, ParentAgentID: rootID, ChildAgentID: "child", + Model: "child-model", Provider: "child-provider", Effort: "low", CWD: childCWD, + }); err != nil { + t.Fatal(err) + } + rootCWD := t.TempDir() + if err := store.SetModelSelection(rootID, "new-model", "new-provider", "high"); err != nil { + t.Fatal(err) + } + if err := store.SetWorkingDirectory(rootID, rootCWD); err != nil { + t.Fatal(err) + } + + want := map[string]RuntimeAgent{ + rootID: {Model: "new-model", Provider: "new-provider", Effort: "high", CWD: rootCWD}, + "child": {Model: "child-model", Provider: "child-provider", Effort: "low", CWD: childCWD}, + } + check := func(reader string, agent RuntimeAgent) { + t.Helper() + expected, ok := want[agent.ID] + if !ok { + t.Fatalf("%s returned unexpected agent %q", reader, agent.ID) + } + if agent.Model != expected.Model || agent.Provider != expected.Provider || agent.Effort != expected.Effort || agent.CWD != expected.CWD { + t.Fatalf("%s %s = %s/%s/%s/%s, want %s/%s/%s/%s", reader, agent.ID, + agent.Model, agent.Provider, agent.Effort, agent.CWD, + expected.Model, expected.Provider, expected.Effort, expected.CWD) + } + } + for _, id := range []string{rootID, "child"} { + agent, err := store.LoadAgent(ctx, rootID, id) + if err != nil { + t.Fatal(err) + } + check("LoadAgent", agent) + } + snapshot, err := store.SnapshotRoot(ctx, rootID) + if err != nil { + t.Fatal(err) + } + if len(snapshot.Agents) != 2 { + t.Fatalf("snapshot agents = %d, want 2", len(snapshot.Agents)) + } + for _, agent := range snapshot.Agents { + check("SnapshotRoot", agent) + } + views, err := store.RootAgentViews(ctx, rootID) + if err != nil { + t.Fatal(err) + } + if len(views) != 2 { + t.Fatalf("root agent views = %d, want 2", len(views)) + } + for _, agent := range views { + check("RootAgentViews", agent) + } +} diff --git a/internal/session/swarm.go b/internal/session/swarm.go index 850343d63..671e97261 100644 --- a/internal/session/swarm.go +++ b/internal/session/swarm.go @@ -333,9 +333,20 @@ func (s *Store) TerminalizeSubtree(ctx context.Context, rootID, callerAgentID, t return eventSeq, nil } +// rootSelectionColumns reads the root agent's model, provider, effort and cwd +// from its session row, where session.model, session.effort and workspace.set +// write them; the copy on the root's agents row is only refreshed at open. +// Children keep the selection they were admitted with. Requires the query to +// join `agents a` with `sessions s`. +const rootSelectionColumns = `CASE WHEN a.parent_id IS NULL THEN s.model ELSE a.model END,` + + `CASE WHEN a.parent_id IS NULL THEN s.provider ELSE a.provider END,` + + `CASE WHEN a.parent_id IS NULL THEN s.effort ELSE a.effort END,` + + `CASE WHEN a.parent_id IS NULL THEN s.cwd ELSE a.cwd END` + func loadAgentTx(ctx context.Context, tx *sql.Tx, rootID, agentID string) (RuntimeAgent, error) { var agent RuntimeAgent - err := tx.QueryRowContext(ctx, `SELECT id,root_id,COALESCE(parent_id,''),name,model,provider,effort,cwd,report,status,last_turn,(SELECT execution_engine FROM sessions WHERE id=agents.root_id) FROM agents WHERE root_id=? AND id=?`, rootID, agentID). + err := tx.QueryRowContext(ctx, `SELECT a.id,a.root_id,COALESCE(a.parent_id,''),a.name,`+rootSelectionColumns+`,a.report,a.status,a.last_turn,s.execution_engine + FROM agents a JOIN sessions s ON s.id=a.root_id WHERE a.root_id=? AND a.id=?`, rootID, agentID). Scan(&agent.ID, &agent.RootID, &agent.ParentID, &agent.Name, &agent.Model, &agent.Provider, &agent.Effort, &agent.CWD, &agent.Report, &agent.Status, &agent.LastTurn, &agent.ExecutionEngine) if errors.Is(err, sql.ErrNoRows) { return RuntimeAgent{}, ErrAgentAccess From 8f3173c02f0eba3c1ad383ea05f4e49f6f90b891 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sun, 27 Sep 2026 16:37:24 -0700 Subject: [PATCH 06/67] refactor(daemon): read saved session facts from the store, not a row mirror Session kept a full session.Meta captured at open. Its ID was used everywhere; the rest mixed identity, the installed runner's selection, saved facts read at decision time, and two write-only mirrors nobody read. Turn completion wrote model and provider back to sessions from that mirror, which was harmless only because model changes are refused mid-turn. Replace the mirror with immutable identity (id, kind, engine, definition revision) and the applied selection (model, provider, effort). Read the goal at turn completion and the directory on request through the store. Drop the model/provider fields from RootTurnCommit and its sessions writeback; the selection commands own that row. Two ordering fixes ride along: session.effort persists before it applies the runner level, so a rejected save leaves every reader at the previous value, and goal.set/goal.run refuse while a client operation is busy, matching effort, model and workspace, so a goal formulation and an explicit goal cannot overwrite each other. Co-Authored-By: Claude Fable 5.1 --- docs/concurrency.md | 21 +++ internal/daemon/agent_session.go | 4 +- internal/daemon/attachments.go | 6 +- internal/daemon/attachments_test.go | 4 +- internal/daemon/budget.go | 18 +-- internal/daemon/cancel_target.go | 6 +- internal/daemon/client_control.go | 139 ++++++++--------- .../daemon/client_control_coverage_test.go | 2 +- internal/daemon/client_control_test.go | 9 +- internal/daemon/context_history_test.go | 2 +- internal/daemon/daemon.go | 2 +- internal/daemon/execution_engine_test.go | 4 +- internal/daemon/hooks.go | 2 +- internal/daemon/hooks_test.go | 2 +- internal/daemon/identity_test.go | 6 +- internal/daemon/input_test.go | 2 +- internal/daemon/metadata_routing_test.go | 7 +- internal/daemon/permission.go | 26 ++-- internal/daemon/permission_mode_test.go | 2 +- internal/daemon/permission_test.go | 6 +- internal/daemon/prompt.go | 4 +- internal/daemon/question.go | 4 +- internal/daemon/recursive_runtime.go | 4 +- internal/daemon/recursive_state.go | 4 +- internal/daemon/rlm.go | 56 +++---- internal/daemon/scheduler.go | 4 +- internal/daemon/session.go | 140 ++++++++++-------- .../daemon/session_state_ownership_test.go | 127 ++++++++++++++++ internal/daemon/session_test.go | 2 +- internal/daemon/spans.go | 16 +- internal/daemon/state.go | 28 ++-- internal/daemon/v2_event_schema_test.go | 2 +- internal/daemon/v2_sdk_repl_test.go | 2 +- internal/daemon/view.go | 2 +- internal/session/command_test.go | 2 +- internal/session/input_lifecycle_test.go | 12 +- internal/session/otlp_export_test.go | 4 +- internal/session/runtime.go | 5 +- internal/session/runtime_storage_test.go | 6 +- internal/session/runtime_test.go | 12 +- internal/session/span_test.go | 2 +- internal/session/title_admission_test.go | 4 +- internal/session/title_test.go | 1 - internal/session/transcript_test.go | 4 +- 44 files changed, 439 insertions(+), 278 deletions(-) create mode 100644 internal/daemon/session_state_ownership_test.go diff --git a/docs/concurrency.md b/docs/concurrency.md index bf56d227d..e28da4267 100644 --- a/docs/concurrency.md +++ b/docs/concurrency.md @@ -37,6 +37,27 @@ disconnected -> reconnecting -> snapshotting -> live A retry with the same command ID retrieves the stored status or outcome. It does not execute the operation twice. +### Session state ownership + +Saved facts (title, goal, archive state, directory, the selected model and +effort) belong to the session store and are read there at the decision that +needs them. The daemon `Session` keeps only immutable identity (ID, kind, +execution engine, definition revision) and the installed runner's selection +(model, provider, effort), which changes only when a runner is installed or +its effort changes. No daemon object holds a copy of the sessions row. + +The root agent's `agents` row copies model, provider, effort and cwd at open; +every agent read derives the root's values from `sessions` instead, so +`agents.inspect` and root snapshots agree with `sessions.get` after a live +change. Children keep the selection they were admitted with. + +Mutations persist before they apply: a rejected effort save leaves the runner +at the previous level. `goal.set` and `goal.run` refuse while a client +operation is busy, like effort, model and workspace changes, so a goal +formulation and an explicit goal cannot overwrite each other. Turn completion +no longer writes model or provider back to `sessions`; the selection commands +own that row. + ## Recursive agents Each live agent has one serialized kernel because its guest heap belongs diff --git a/internal/daemon/agent_session.go b/internal/daemon/agent_session.go index fd45e908e..cfbd6e92b 100644 --- a/internal/daemon/agent_session.go +++ b/internal/daemon/agent_session.go @@ -626,12 +626,12 @@ func (session *AgentSession) bind(root *Session) error { return value.ReferenceID, nil }) if root.executors != nil { - session.agent.Services.SetCustomTools(root.definition.ID, root.meta.DefinitionRevision, customTools(root.definition), root.executors) + session.agent.Services.SetCustomTools(root.definition.ID, root.definitionRevision, customTools(root.definition), root.executors) } if err := session.agent.Services.BindDispatcher(root.store, root.store.Workspaces(), root.store.Processes(), root.authority); err != nil { return err } - session.agent.SetSessionID(root.meta.ID) + session.agent.SetSessionID(root.id) session.bindPresentation(root) return nil } diff --git a/internal/daemon/attachments.go b/internal/daemon/attachments.go index 796b6006d..63c487e07 100644 --- a/internal/daemon/attachments.go +++ b/internal/daemon/attachments.go @@ -83,7 +83,7 @@ func (s *Server) validateCommandAttachments(ctx context.Context, clientID string if _, err := designContextPresentation(SubmitPayload{Attachments: payload.Attachments, DesignContext: payload.DesignContext}); err != nil { return nil, err } - agentID := root.meta.ID + agentID := root.id if params.Operation == "agent.submit" { agentID = payload.ID if agentID == "" { @@ -100,7 +100,7 @@ func (s *Session) validateAttachmentReferences(ctx context.Context, agentID stri return rpcFailure(-32602, err.Error()) } for _, attachment := range attachments { - _, meta, err := s.store.ReadContent(ctx, attachment.Content.ReferenceID, s.meta.ID, agentID, 0, 1) + _, meta, err := s.store.ReadContent(ctx, attachment.Content.ReferenceID, s.id, agentID, 0, 1) if err != nil { return err } @@ -120,7 +120,7 @@ func (s *Session) resolveAttachments(ctx context.Context, agentID string, payloa content := attachment.Content data := make([]byte, 0, int(content.Size)) for offset := int64(0); ; { - chunk, meta, err := s.store.ReadContent(ctx, content.ReferenceID, s.meta.ID, agentID, offset, min(MaxContentChunk, max(1, int(content.Size-offset)))) + chunk, meta, err := s.store.ReadContent(ctx, content.ReferenceID, s.id, agentID, offset, min(MaxContentChunk, max(1, int(content.Size-offset)))) if err != nil { if errors.Is(err, session.ErrContentAccess) || errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrPermission) { return "", nil, fmt.Errorf("%w: read attachment: %w", session.ErrInvalidInput, err) diff --git a/internal/daemon/attachments_test.go b/internal/daemon/attachments_test.go index e2e03d01b..5201827fa 100644 --- a/internal/daemon/attachments_test.go +++ b/internal/daemon/attachments_test.go @@ -121,7 +121,7 @@ func TestAttachmentCorruptionAndCancellation(t *testing.T) { directory := t.TempDir() store := openStore(t, filepath.Join(directory, "sessions.db")) rootID := createRoot(t, store) - node := &AgentSession{id: rootID, root: &Session{store: store, meta: session.Meta{ID: rootID}}} + node := &AgentSession{id: rootID, root: &Session{store: store, id: rootID}} attachment := inputAttachment(t, node, "", "text", "text/plain", []byte("valid")) payload := SubmitPayload{Attachments: []protocol.InputAttachment{attachment}} ctx, cancel := context.WithCancel(t.Context()) @@ -181,7 +181,7 @@ func TestAttachmentChildUploadAndInboxAcrossTransports(t *testing.T) { t.Fatalf("upload broadened scope to %q: %v", id, err) } } - root := &Session{store: f.store, meta: session.Meta{ID: f.rootID}} + root := &Session{store: f.store, id: f.rootID} attachment := protocol.InputAttachment{Kind: "text", Content: handle} for _, delivery := range []string{"queued", "steer"} { output, err := root.clientAgentSubmitInput(t.Context(), "child", SubmitPayload{Attachments: []protocol.InputAttachment{attachment}}, delivery) diff --git a/internal/daemon/budget.go b/internal/daemon/budget.go index 759f5d1ae..670adf0ff 100644 --- a/internal/daemon/budget.go +++ b/internal/daemon/budget.go @@ -12,13 +12,13 @@ import ( ) func (s *Session) consumeBudgets(ctx context.Context, agentID string, reservations []capability.Reservation, action func() error) error { - if err := s.store.ReserveBudget(ctx, s.meta.ID, agentID, reservations); err != nil { + if err := s.store.ReserveBudget(ctx, s.id, agentID, reservations); err != nil { return err } if err := action(); err != nil { - return errors.Join(err, s.store.ReleaseBudget(context.WithoutCancel(ctx), s.meta.ID, agentID, reservations)) + return errors.Join(err, s.store.ReleaseBudget(context.WithoutCancel(ctx), s.id, agentID, reservations)) } - return s.store.ReconcileBudget(context.WithoutCancel(ctx), s.meta.ID, agentID, reservations, nil) + return s.store.ReconcileBudget(context.WithoutCancel(ctx), s.id, agentID, reservations, nil) } func durableReservations(bytes int) []capability.Reservation { @@ -57,7 +57,7 @@ func (s *Session) beginAgentModelAttempt(ctx context.Context, agentID string, at if err := s.flushPendingAccountingLocked(); err != nil { return sessionstore.ModelCallReservation{}, errors.New("model accounting is unresolved; further calls are paused") } - return s.store.AdmitModelCall(actorCtx, s.meta.ID, agentID, attempt) + return s.store.AdmitModelCall(actorCtx, s.id, agentID, attempt) }) if err != nil { return llm.ModelPermit{}, err @@ -84,7 +84,7 @@ func (s *Session) beginAgentModelAttempt(ctx context.Context, agentID string, at settleCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var err error - settled, err = s.store.SettleModelCall(settleCtx, s.meta.ID, reservation.ID, result) + settled, err = s.store.SettleModelCall(settleCtx, s.id, reservation.ID, result) if err != nil { if errors.Is(err, sessionstore.ErrModelCallConflict) { return err @@ -120,7 +120,7 @@ func (s *Session) flushPendingAccountingLocked() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() for id, result := range s.pendingAccounting { - if _, err := s.store.SettleModelCall(ctx, s.meta.ID, id, result); err != nil { + if _, err := s.store.SettleModelCall(ctx, s.id, id, result); err != nil { return err } delete(s.pendingAccounting, id) @@ -129,7 +129,7 @@ func (s *Session) flushPendingAccountingLocked() error { } func (s *Session) publishModelAccounting(ctx context.Context) { - accounting, err := s.store.ModelAccounting(ctx, s.meta.ID, "", true) + accounting, err := s.store.ModelAccounting(ctx, s.id, "", true) if err == nil { s.supervisor.post(workerEnvelope{kind: workerStream, stream: &streamEnvelope{ kind: "stream.accounting", event: StreamEvent{Accounting: &accounting}, @@ -145,12 +145,12 @@ func (s *Session) modelAccountingNotice(agentID, text string) { func (s *Session) InspectBudgets(ctx context.Context, callerAgentID, targetAgentID string) ([]sessionstore.BudgetState, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.BudgetState, error) { - return s.store.InspectBudgetsFor(actorCtx, s.meta.ID, callerAgentID, targetAgentID) + return s.store.InspectBudgetsFor(actorCtx, s.id, callerAgentID, targetAgentID) }) } func (s *Session) CapBudget(ctx context.Context, callerAgentID, targetAgentID string, kind sessionstore.BudgetKind, limit int64) (sessionstore.BudgetState, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.BudgetState, error) { - return s.store.CapBudget(actorCtx, s.meta.ID, callerAgentID, targetAgentID, kind, limit) + return s.store.CapBudget(actorCtx, s.id, callerAgentID, targetAgentID, kind, limit) }) } diff --git a/internal/daemon/cancel_target.go b/internal/daemon/cancel_target.go index 09ec07683..d361b5252 100644 --- a/internal/daemon/cancel_target.go +++ b/internal/daemon/cancel_target.go @@ -11,7 +11,7 @@ func (s *Session) checkTurnTarget(ctx context.Context, agentID, turnID string) e if agentID == "" || turnID == "" { return rpcFailure(-32602, "cancellation requires a specific agent and turn ID") } - active, err := s.store.ActiveTurn(ctx, s.meta.ID, agentID) + active, err := s.store.ActiveTurn(ctx, s.id, agentID) if err != nil { return err } @@ -22,7 +22,7 @@ func (s *Session) checkTurnTarget(ctx context.Context, agentID, turnID string) e } func (s *Session) cancelInputCommand(ctx context.Context, clientID, commandID string) error { - record, cancelled, err := s.store.CancelQueuedInput(ctx, s.meta.ID, clientID, commandID, encodeCommandOutcome("cancel", "", context.Canceled)) + record, cancelled, err := s.store.CancelQueuedInput(ctx, s.id, clientID, commandID, encodeCommandOutcome("cancel", "", context.Canceled)) if errors.Is(err, sessionstore.ErrCommandTarget) { return rpcFailure(-32009, err.Error()) } @@ -39,7 +39,7 @@ func (s *Session) cancelInputCommand(ctx context.Context, clientID, commandID st } // The root actor owns one live model turn. Running root inbox rows are // either its initial input or steering already claimed by that same turn. - turnID, err := s.store.ActiveTurn(ctx, s.meta.ID, s.authority.AgentID) + turnID, err := s.store.ActiveTurn(ctx, s.id, s.authority.AgentID) if err != nil { return err } diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index dc574fa6b..eb340da33 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -354,11 +354,11 @@ func (s *Session) AcceptClientCommand(ctx context.Context, admission sessionstor } func (s *Session) clientCommand(ctx context.Context, admission sessionstore.CommandAdmission, operation string, payload json.RawMessage, wait bool) (CommandResult, error) { - if s.meta.Kind == sessionstore.SessionKindToolHost && !isToolHostOperation(operation) { + if s.kind == sessionstore.SessionKindToolHost && !isToolHostOperation(operation) { return CommandResult{}, fmt.Errorf("tool-host sessions do not support %q", operation) } admission.Scope = sessionstore.CommandScopeRoot - admission.RootID = s.meta.ID + admission.RootID = s.id admission.AgentID = s.authority.AgentID admission.Kind = operation admission.Payload.Data = slices.Clone(admission.Payload.Data) @@ -382,7 +382,7 @@ func (s *Session) clientCommand(ctx context.Context, admission sessionstore.Comm if admitted.Command.Status == "queued" || admitted.Command.Status == "running" || admitted.Command.Status == "waiting" { return finish(nil) } - body, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.meta.ID, admitted.Command.Outcome) + body, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.id, admitted.Command.Outcome) if resolveErr != nil { return finish(resolveErr) } @@ -448,7 +448,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi } if operation == "session.reload" && (s.hasRunningAgent() || s.clientBusy) { s.reloadPending = true - output, _ := marshalClientOutput(protocol.ModelResult{Model: s.meta.Model, Provider: s.meta.Provider, ReloadPending: true}, nil) + output, _ := marshalClientOutput(protocol.ModelResult{Model: s.model, Provider: s.provider, ReloadPending: true}, nil) return finish(s.finishClientCommandInline(actorCtx, admission, operation, output, nil, &result)) } if s.hasRunningAgent() || s.clientBusy || s.clientIntegrations > 0 { @@ -456,15 +456,15 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi } model, provider := action.Model, action.Provider if operation == "session.reload" || operation == "compaction.configure" { - model, provider = s.meta.Model, s.meta.Provider + model, provider = s.model, s.provider } if provider == "" { - provider = s.meta.Provider + provider = s.provider } if model == "" { return finish(s.finishClientCommandInline(actorCtx, admission, operation, "", errors.New("model is required"), &result)) } - if operation == "session.model" && model == s.meta.Model && provider == s.meta.Provider && action.Effort == "" { + if operation == "session.model" && model == s.model && provider == s.provider && action.Effort == "" { var err error if action.PersistDefault { _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { cfg.DefaultModel, cfg.DefaultProvider = model, provider; return nil }) @@ -480,7 +480,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi return finish(s.finishClientCommandInline(actorCtx, admission, operation, "", fmt.Errorf("model cannot change while %w", err), &result)) } } - factory, rootID := s.factory, s.meta.ID + factory, rootID := s.factory, s.id s.clientBusy = true s.clientPreparing = true asyncReply = completionReply @@ -694,7 +694,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi } cut := action.Cut if action.ExpectedRevision != nil { - if err := s.store.CheckHistoryRevision(actorCtx, s.meta.ID, *action.ExpectedRevision); err != nil { + if err := s.store.CheckHistoryRevision(actorCtx, s.id, *action.ExpectedRevision); err != nil { return finish(s.finishClientCommandInline(actorCtx, admission, operation, "", err, &result)) } } @@ -704,7 +704,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi if _, ok := s.runner.(clientHistoryRunner); !ok { return finish(s.finishClientCommandInline(actorCtx, admission, operation, "", errors.New("session runner does not support history replacement"), &result)) } - snapshots, err := s.store.WorkspaceSnapshotsFrom(actorCtx, s.meta.ID, cut) + snapshots, err := s.store.WorkspaceSnapshotsFrom(actorCtx, s.id, cut) if err != nil { return finish(s.finishClientCommandInline(actorCtx, admission, operation, "", err, &result)) } @@ -806,14 +806,14 @@ func (s *Session) completeClientCommand(completion *clientCommandCompletion) (Co }) } if completion.output == "" { - completion.output, _ = marshalClientOutput(protocol.ModelResult{Model: s.meta.Model, Provider: s.meta.Provider, ReloadPending: s.reloadPending}, nil) + completion.output, _ = marshalClientOutput(protocol.ModelResult{Model: s.model, Provider: s.provider, ReloadPending: s.reloadPending}, nil) } } if completion.automatic { if completion.err != nil { payload, _ := json.Marshal(sessionstore.LifecycleEvent{Error: completion.err.Error()}) - _, err := s.store.AppendRootEvent(s.supervisor.ctx, s.meta.ID, "session.reload.failed", sessionstore.RuntimePayload{Data: payload, MediaType: "application/json", Source: "session reload failure"}) + _, err := s.store.AppendRootEvent(s.supervisor.ctx, s.id, "session.reload.failed", sessionstore.RuntimePayload{Data: payload, MediaType: "application/json", Source: "session reload failure"}) return CommandResult{}, err } return CommandResult{}, nil @@ -824,10 +824,10 @@ func (s *Session) completeClientCommand(completion *clientCommandCompletion) (Co var err error if compaction.rawCutoff != nil { rawCutoff = *compaction.rawCutoff - err = s.store.RecordRawCompaction(s.supervisor.ctx, s.meta.ID, s.meta.ID, rawCutoff, compaction.summary, compaction.pinned) + err = s.store.RecordRawCompaction(s.supervisor.ctx, s.id, s.id, rawCutoff, compaction.summary, compaction.pinned) } else { rawCutoff = s.rawCompactionCutoff(compaction.cutoff, compaction.rawTailStart) - err = s.store.RecordCompaction(s.meta.ID, rawCutoff, compaction.summary) + err = s.store.RecordCompaction(s.id, rawCutoff, compaction.summary) } if err != nil { if runner, ok := s.runner.(clientCompactRunner); ok { @@ -839,14 +839,14 @@ func (s *Session) completeClientCommand(completion *clientCommandCompletion) (Co } completion.err = err } else { - _ = s.store.SetUsage(s.meta.ID, compaction.usage.PromptTokens, compaction.usage.Cached(), compaction.usage.CompletionTokens) + _ = s.store.SetUsage(s.id, compaction.usage.PromptTokens, compaction.usage.Cached(), compaction.usage.CompletionTokens) var outputErr error completion.output, outputErr = marshalClientOutput(protocol.CompactionResult{Cutoff: rawCutoff, Model: compaction.model, Usage: compaction.usage}, nil) completion.err = errors.Join(completion.err, outputErr) } } if completion.rewind != nil && completion.err == nil { - history, err := s.store.RewindHistory(s.supervisor.ctx, s.meta.ID, completion.rewind.cut) + history, err := s.store.RewindHistory(s.supervisor.ctx, s.id, completion.rewind.cut) if err != nil { completion.err = err } else { @@ -856,15 +856,14 @@ func (s *Session) completeClientCommand(completion *clientCommandCompletion) (Co } if completion.goal != nil && completion.err == nil { goal := completion.goal - if err := s.store.SetGoal(s.meta.ID, goal.text); err != nil { + if err := s.store.SetGoal(s.id, goal.text); err != nil { completion.err = err } else if _, err := s.enqueue(s.supervisor.ctx, "goal", goal.text, false); err != nil { completion.err = err } else { - s.meta.Goal = goal.text s.goalRounds = 0 completion.output = goal.text - _ = s.store.SetUsage(s.meta.ID, goal.usage.PromptTokens, goal.usage.Cached(), goal.usage.CompletionTokens) + _ = s.store.SetUsage(s.id, goal.usage.PromptTokens, goal.usage.Cached(), goal.usage.CompletionTokens) } } result := CommandResult{CommandID: completion.commandID, IngressSeq: completion.ingress} @@ -875,9 +874,9 @@ func (s *Session) completeClientCommand(completion *clientCommandCompletion) (Co } func (s *Session) rawCompactionCutoff(cutoff, rawTailStart int) int { - events := s.store.Compactions(s.meta.ID) + events := s.store.Compactions(s.id) if len(events) == 0 { - raw := s.store.RawMessages(s.meta.ID) + raw := s.store.RawMessages(s.id) if len(raw) > 0 && raw[0].Role != "system" { return cutoff - 1 } @@ -912,7 +911,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if !ok { return "", errors.New("session runner does not support external permissions") } - if err := s.store.SetPermissionMode(ctx, s.meta.ID, permissionModeLabel(payload.ExternalPermissions)); err != nil { + if err := s.store.SetPermissionMode(ctx, s.id, permissionModeLabel(payload.ExternalPermissions)); err != nil { return "", err } runner.SetExternalPermissions(payload.ExternalPermissions) @@ -952,7 +951,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw } // Headless mode prevents waiting for new consent. Automatic mode is // already a durable user authorization and keeps that same policy. - permissionMode, err := s.store.PermissionMode(ctx, s.meta.ID) + permissionMode, err := s.store.PermissionMode(ctx, s.id) if err != nil { return "", err } @@ -960,8 +959,8 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw s.applyRunConfiguration(runner, s.runtime, permissionMode) return "configured", nil case "inbox.steer", "inbox.remove": - result, err := s.store.ControlInbox(ctx, s.meta.ID, payload.ID, payload.InboxSeq, payload.TurnID, operation == "inbox.remove", []byte(`{"code":-32800,"message":"Queued message removed","data":{"kind":"queue_removed"}}`)) - if err == nil && result.Status == "removed" && payload.ID == s.meta.ID { + result, err := s.store.ControlInbox(ctx, s.id, payload.ID, payload.InboxSeq, payload.TurnID, operation == "inbox.remove", []byte(`{"code":-32800,"message":"Queued message removed","data":{"kind":"queue_removed"}}`)) + if err == nil && result.Status == "removed" && payload.ID == s.id { s.settle(payload.InboxSeq, Completion{Sequence: payload.InboxSeq, Err: context.Canceled}) } if err == nil { @@ -981,11 +980,13 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if !s.definition.Surface.GoalLoop { return "", errors.New("this agent does not run goals") } + if s.running != nil || s.clientBusy { + return "", errors.New("goal cannot change while a root operation is running") + } goal := strings.TrimSpace(payload.Text) - if err := s.store.SetGoal(s.meta.ID, goal); err != nil { + if err := s.store.SetGoal(s.id, goal); err != nil { return "", err } - s.meta.Goal = goal s.goalRounds = 0 if operation == "goal.run" && goal != "" { if _, err := s.enqueue(ctx, "goal", goal, false); err != nil { @@ -997,7 +998,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw return s.clientSchedule(ctx, operation, payload) case "session.fork": if payload.ExpectedRevision != nil { - if err := s.store.CheckHistoryRevision(ctx, s.meta.ID, *payload.ExpectedRevision); err != nil { + if err := s.store.CheckHistoryRevision(ctx, s.id, *payload.ExpectedRevision); err != nil { return "", err } } @@ -1007,7 +1008,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw } title := strings.TrimSpace(payload.Title) if title == "" { - source, err := s.store.LoadMeta(s.meta.ID) + source, err := s.store.LoadMeta(s.id) if err != nil { return "", err } @@ -1016,7 +1017,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw return "", err } } - id, err := s.store.Fork(s.meta.ID, cut, title) + id, err := s.store.Fork(s.id, cut, title) if err == nil { s.notifyTitleChanged(id) } @@ -1025,7 +1026,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if runner, ok := s.runner.(clientWorkspaceRunner); ok { return runner.ResolveWorkingDirectory(".") } - return s.meta.CWD, nil + return s.WorkingDirectory(), nil case "workspace.set": if s.running != nil || s.clientBusy { return "", errors.New("working directory cannot change while the root agent is running") @@ -1038,15 +1039,14 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if err != nil { return "", err } - if err := s.store.SetWorkingDirectory(s.meta.ID, path); err != nil { + if err := s.store.SetWorkingDirectory(s.id, path); err != nil { return "", err } runner.SetWorkingDirectory(path) - s.meta.CWD = path s.emitSessionUpdate(ctx, "session.cwd.updated", SessionUpdateEvent{WorkingDir: path}) return path, nil case "session.effort.get": - return daemonEffortLabel(s.meta.Effort), nil + return daemonEffortLabel(s.effort), nil case "session.effort": requested := strings.TrimSpace(payload.Effort) if requested == "" { @@ -1055,7 +1055,12 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if s.running != nil || s.clientBusy { return "", errors.New("effort cannot change while the root agent is running") } - if err := validateEffort(s.meta.Model, s.meta.Provider, requested); err != nil { + if err := validateEffort(s.model, s.provider, requested); err != nil { + return "", err + } + // Persist first: a rejected save must leave the runner and every other + // client at the previous level. + if err := s.store.SetEffort(s.id, requested); err != nil { return "", err } level := requested @@ -1065,10 +1070,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if setter, ok := s.runner.(interface{ SetEffort(string) }); ok { setter.SetEffort(level) } - if err := s.store.SetEffort(s.meta.ID, requested); err != nil { - return "", err - } - s.meta.Effort = requested + s.effort = requested if payload.PersistDefault { if _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { cfg.DefaultEffort = requested; return nil }); err != nil { return "", err @@ -1078,7 +1080,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw s.emitSessionUpdate(ctx, "session.effort.updated", SessionUpdateEvent{Effort: requested, EffortChanged: true}) return daemonEffortLabel(requested), nil case "session.model.get": - return marshalClientOutput(protocol.ModelResult{Model: s.meta.Model, Provider: s.meta.Provider}, nil) + return marshalClientOutput(protocol.ModelResult{Model: s.model, Provider: s.provider}, nil) case "session.list": metas, err := s.store.RecentContext(ctx, 50) @@ -1100,7 +1102,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if title == "" { return "", errors.New("session title is required") } - if err := s.store.SetTitle(s.meta.ID, title); err != nil { + if err := s.store.SetTitle(s.id, title); err != nil { return "", err } if s.titleWork != nil { @@ -1109,15 +1111,14 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw } return title, s.publishTitle(ctx, title) case "session.archive": - if err := s.store.SetArchived(ctx, s.meta.ID, payload.Archived); err != nil { + if err := s.store.SetArchived(ctx, s.id, payload.Archived); err != nil { return "", err } - s.meta.Archived = payload.Archived output, err := marshalClientOutput(protocol.ArchiveResult{Archived: payload.Archived}, nil) if err != nil { return "", err } - _, err = s.store.AppendRootEvent(ctx, s.meta.ID, "session.archived.updated", sessionstore.RuntimePayload{ + _, err = s.store.AppendRootEvent(ctx, s.id, "session.archived.updated", sessionstore.RuntimePayload{ Data: []byte(output), MediaType: "application/json", Source: "session.archive", }) return output, err @@ -1126,7 +1127,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw return "", errors.New("history cannot change while a turn is running") } if payload.ExpectedRevision != nil { - if err := s.store.CheckHistoryRevision(ctx, s.meta.ID, *payload.ExpectedRevision); err != nil { + if err := s.store.CheckHistoryRevision(ctx, s.id, *payload.ExpectedRevision); err != nil { return "", err } } @@ -1134,7 +1135,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if !ok { return "", errors.New("session runner does not support history replacement") } - snapshots, err := s.store.WorkspaceSnapshotsFrom(ctx, s.meta.ID, 1) + snapshots, err := s.store.WorkspaceSnapshotsFrom(ctx, s.id, 1) if err != nil { return "", err } @@ -1142,7 +1143,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if len(snapshots) > 0 && !canDrop { return "", errors.New("session runner cannot release workspace snapshots") } - history, err := s.store.RewindHistory(ctx, s.meta.ID, 1) + history, err := s.store.RewindHistory(ctx, s.id, 1) if err != nil { return "", err } @@ -1161,20 +1162,20 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw case "provider.catalogs": return clientProviderCatalogs(ctx, s.providers, false) case "history.compact.log": - return marshalClientOutput(s.store.Compactions(s.meta.ID), nil) + return marshalClientOutput(s.store.Compactions(s.id), nil) case "history.compact.retry": if s.running != nil || s.clientBusy { return "", errors.New("history cannot change while a turn is running") } - events := s.store.Compactions(s.meta.ID) + events := s.store.Compactions(s.id) if len(events) == 0 { return marshalClientOutput(protocol.CompactionRetryResult{}, nil) } last := events[len(events)-1] - if err := s.store.DeleteCompaction(s.meta.ID, last.Seq); err != nil { + if err := s.store.DeleteCompaction(s.id, last.Seq); err != nil { return "", err } - _, history, err := s.store.Load(s.meta.ID) + _, history, err := s.store.Load(s.id) if err != nil { return "", err } @@ -1184,7 +1185,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw return marshalClientOutput(protocol.CompactionRetryResult{Undone: true, Sequence: last.Seq}, nil) case "agents.list": - agents, err := s.store.RootAgentViews(ctx, s.meta.ID) + agents, err := s.store.RootAgentViews(ctx, s.id) return marshalClientOutput(agents, err) case "agent.transcript": return s.clientAgentTranscript(ctx, payload.ID) @@ -1207,14 +1208,14 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw record, err := s.revokeCapability(ctx, s.authority.AgentID, strings.TrimSpace(payload.ID)) return marshalClientOutput(record, err) case "permission.rules": - rules, err := s.store.ListPermissionRules(ctx, s.meta.ID) + rules, err := s.store.ListPermissionRules(ctx, s.id) if err != nil { return "", err } return marshalClientOutput(protocol.PermissionRulesResult{Rules: rules, Global: s.store.GlobalPermissionRules()}, nil) case "permission.forget": id := strings.TrimSpace(payload.ID) - if err := s.store.DeletePermissionRule(ctx, s.meta.ID, id); err != nil { + if err := s.store.DeletePermissionRule(ctx, s.id, id); err != nil { return "", err } return "forgot rule " + id, nil @@ -1529,14 +1530,14 @@ func (s *Session) installReplacement(ctx context.Context, replacement *clientRep } configureMCP(s, components) if runner, ok := components.Runner.(clientRunRunner); ok && s.runConfig != nil { - permissionMode, err := s.store.PermissionMode(ctx, s.meta.ID) + permissionMode, err := s.store.PermissionMode(ctx, s.id) if err != nil { cleanup() return "", err } s.applyRunConfiguration(runner, components.Runtime, permissionMode) } - if err := s.store.SetModelSelection(s.meta.ID, model, provider, meta.Effort); err != nil { + if err := s.store.SetModelSelection(s.id, model, provider, meta.Effort); err != nil { cleanup() return "", err } @@ -1550,7 +1551,7 @@ func (s *Session) installReplacement(ctx context.Context, replacement *clientRep s.mcpMu.Unlock() s.runner, s.runtime = components.Runner, components.Runtime replacement.installed = true - s.meta.Model, s.meta.Provider, s.meta.Effort = model, provider, meta.Effort + s.model, s.provider, s.effort = model, provider, meta.Effort s.emitSessionUpdate(ctx, "session.model.updated", SessionUpdateEvent{ Model: model, Provider: provider, Effort: meta.Effort, EffortChanged: true, }) @@ -1646,7 +1647,7 @@ func (s *Session) emitSessionUpdate(ctx context.Context, kind string, event Sess if err != nil { return } - _, _ = s.store.AppendRootEvent(ctx, s.meta.ID, kind, sessionstore.RuntimePayload{ + _, _ = s.store.AppendRootEvent(ctx, s.id, kind, sessionstore.RuntimePayload{ Data: payload, MediaType: "application/json", Source: kind, }) } @@ -1655,7 +1656,7 @@ func (r *AgentSession) SetEffort(level string) { r.agent.Effort = level } func (s *Session) clientSchedule(ctx context.Context, operation string, payload clientActionPayload) (string, error) { if operation == "schedule.list" { - schedules, err := s.store.SchedulesContext(ctx, s.meta.ID) + schedules, err := s.store.SchedulesContext(ctx, s.id) return marshalClientOutput(schedules, err) } if operation == "schedule.delete" { @@ -1663,7 +1664,7 @@ func (s *Session) clientSchedule(ctx context.Context, operation string, payload if id < 1 { return "", errors.New("schedule ID must be positive") } - if err := s.store.DeleteSchedule(s.meta.ID, id); err != nil { + if err := s.store.DeleteSchedule(s.id, id); err != nil { return "", err } return marshalClientOutput(protocol.ScheduleResult{ScheduleID: id}, nil) @@ -1683,7 +1684,7 @@ func (s *Session) clientSchedule(ctx context.Context, operation string, payload }) var id int err = s.consumeBudgets(ctx, s.authority.AgentID, reservations, func() error { - id, err = s.store.AddSchedule(s.meta.ID, parsed.String(), prompt, time.Now().UTC()) + id, err = s.store.AddSchedule(s.id, parsed.String(), prompt, time.Now().UTC()) return err }) if err != nil { @@ -1711,11 +1712,11 @@ func (s *Session) clientAgentControl(ctx context.Context, id, status string) (st } func (s *Session) clientAgentTranscript(ctx context.Context, id string) (string, error) { - agentValue, err := s.store.LoadAgent(ctx, s.meta.ID, id) + agentValue, err := s.store.LoadAgent(ctx, s.id, id) if err != nil { return "", err } - snapshot, err := s.store.SnapshotRootView(ctx, s.meta.ID, sessionstore.SnapshotViewOptions{RecentMessages: 1, CollectionLimit: 128, MaxBytes: 128 << 10}) + snapshot, err := s.store.SnapshotRootView(ctx, s.id, sessionstore.SnapshotViewOptions{RecentMessages: 1, CollectionLimit: 128, MaxBytes: 128 << 10}) if err != nil { return "", err } @@ -1725,13 +1726,13 @@ func (s *Session) clientAgentTranscript(ctx context.Context, id string) (string, inbox = append(inbox, item) } } - page, err := s.store.ReadTranscriptPage(ctx, s.meta.ID, id, sessionstore.TranscriptReadOptions{ + page, err := s.store.ReadTranscriptPage(ctx, s.id, id, sessionstore.TranscriptReadOptions{ Recent: true, ThroughSeq: -1, Revision: &snapshot.HistoryRevision, Limit: 64, MaxBytes: 256 << 10, }) if err != nil { return "", err } - accounting, err := s.store.ModelAccounting(ctx, s.meta.ID, id, false) + accounting, err := s.store.ModelAccounting(ctx, s.id, id, false) if err != nil { return "", err } @@ -1763,7 +1764,7 @@ func (s *Session) clientAgentSubmitInput(ctx context.Context, id string, input S if delivery == "steer" { kind = "steer" } - agentValue, err := s.store.LoadAgent(ctx, s.meta.ID, id) + agentValue, err := s.store.LoadAgent(ctx, s.id, id) if err != nil { return "", err } @@ -1782,7 +1783,7 @@ func (s *Session) clientAgentSubmitInput(ctx context.Context, id string, input S kind += ".parts" payload = sessionstore.RuntimePayload{Data: data, MediaType: "application/json", Source: "human child submission"} } - item := sessionstore.InboxEnqueue{RootID: s.meta.ID, AgentID: id, Kind: kind, Payload: payload, Origin: "client"} + item := sessionstore.InboxEnqueue{RootID: s.id, AgentID: id, Kind: kind, Payload: payload, Origin: "client"} if len(admissions) > 0 { item.CommandClientID, item.CommandID = admissions[0].ClientID, admissions[0].CommandID } @@ -1812,7 +1813,7 @@ func (s *Session) clientBudget(ctx context.Context, id, kind string, limit int64 return "", errors.New("budget requires an agent, kind and nonnegative limit") } - state, err := s.store.CapBudget(ctx, s.meta.ID, s.authority.AgentID, id, sessionstore.BudgetKind(kind), limit) + state, err := s.store.CapBudget(ctx, s.id, s.authority.AgentID, id, sessionstore.BudgetKind(kind), limit) if err == nil { // A raised cap can unblock queued descendants; re-derive readiness. s.reconcileAgentWork() @@ -1936,7 +1937,7 @@ func (s *Session) startPendingReload() { s.reloadPending = false s.clientBusy = true s.clientPreparing = true - factory, rootID, model, provider := s.factory, s.meta.ID, s.meta.Model, s.meta.Provider + factory, rootID, model, provider := s.factory, s.id, s.model, s.provider if !s.supervisor.launchWorker("prepare deferred reload", func() { var replacement *clientReplacement var err error diff --git a/internal/daemon/client_control_coverage_test.go b/internal/daemon/client_control_coverage_test.go index 76844426d..740385301 100644 --- a/internal/daemon/client_control_coverage_test.go +++ b/internal/daemon/client_control_coverage_test.go @@ -31,7 +31,7 @@ func controlBoundarySession(t *testing.T) *Session { } supervisor := newSupervisor() t.Cleanup(supervisor.stop) - return &Session{store: store, meta: meta, authority: authority, supervisor: supervisor} + return &Session{store: store, id: meta.ID, kind: meta.Kind, engine: meta.ExecutionEngine, definitionRevision: meta.DefinitionRevision, model: meta.Model, provider: meta.Provider, effort: meta.Effort, authority: authority, supervisor: supervisor} } func TestClientCommandsSettleWhenWorkerAdmissionCloses(t *testing.T) { diff --git a/internal/daemon/client_control_test.go b/internal/daemon/client_control_test.go index b673a57f8..145d47b62 100644 --- a/internal/daemon/client_control_test.go +++ b/internal/daemon/client_control_test.go @@ -324,6 +324,7 @@ func TestShellCommandLeavesActorResponsiveAndQueuesTurns(t *testing.T) { {"goal.from-context", map[string]any{"window": 2}}, {"history.rewind", map[string]any{"cut": 1}}, {"history.clear", map[string]string{}}, + {"goal.set", map[string]any{"text": "blocked"}}, } { result := clientCommand(t, root, "tui", fmt.Sprintf("busy-%d", i), test.operation, test.payload) if result.Status != "failed" || !strings.Contains(result.Error, "running") { @@ -336,9 +337,9 @@ func TestShellCommandLeavesActorResponsiveAndQueuesTurns(t *testing.T) { if _, err := root.Snapshot(snapshotCtx); err != nil { t.Fatalf("snapshot blocked behind shell worker: %v", err) } - goal := clientCommand(t, root, "tui", "goal-during-shell", "goal.set", map[string]any{"text": "stay responsive"}) - if goal.Status != "succeeded" { - t.Fatalf("actor command during shell = %+v", goal) + probe := clientCommand(t, root, "tui", "effort-during-shell", "session.effort.get", map[string]any{}) + if probe.Status != "succeeded" { + t.Fatalf("actor command during shell = %+v", probe) } receipt, err := root.Submit(t.Context(), "after shell") if err != nil { @@ -967,7 +968,7 @@ func TestClientControlReportsUnsupportedRunnerCapabilities(t *testing.T) { if result := clientCommand(t, root, "tui", "idle-cancel", "cancel", map[string]any{}); result.Status != "failed" || !strings.Contains(result.Error, "turn ID") { t.Fatalf("idle cancel = %+v", result) } - if result := clientCommand(t, root, "tui", "workspace-fallback", "workspace.inspect", map[string]any{}); result.Output != root.meta.CWD { + if result := clientCommand(t, root, "tui", "workspace-fallback", "workspace.inspect", map[string]any{}); result.Output != root.WorkingDirectory() { t.Fatalf("workspace fallback = %+v", result) } if result := clientCommand(t, root, "tui", "mcp-fallback", "mcp.status", map[string]any{}); result.Output != "[]" { diff --git a/internal/daemon/context_history_test.go b/internal/daemon/context_history_test.go index 8942bfb48..721229fe2 100644 --- a/internal/daemon/context_history_test.go +++ b/internal/daemon/context_history_test.go @@ -276,7 +276,7 @@ func TestCurrentTurnHistorySurvivesCompactionAndCommitsOnce(t *testing.T) { if _, err := store.EnsureAuthority(t.Context(), fork); err != nil { t.Fatal(err) } - forkNode := &AgentSession{id: fork, root: &Session{store: store, meta: sessionstore.Meta{ID: fork}}, agent: runtime.rootNode.agent} + forkNode := &AgentSession{id: fork, root: &Session{store: store, id: fork}, agent: runtime.rootNode.agent} forkHost := &recursiveHost{session: forkNode} forkResult := historyCall(t, forkHost, "search", map[string]any{"query": needle}) if len(forkResult["matches"].([]map[string]any)) != 1 { diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index cae523ed5..28c509b0d 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -320,7 +320,7 @@ func configureMCP(root *Session, components Components) { if manager, ok := components.MCP.(interface { SetProcessOptions(*capability.ProcessManager, string, string, map[string]string) }); ok { - manager.SetProcessOptions(root.store.Processes(), root.meta.ID, root.meta.CWD, nil) + manager.SetProcessOptions(root.store.Processes(), root.id, root.WorkingDirectory(), nil) } if supervised, ok := components.MCP.(interface { SetLauncher(func(string, func()) bool) diff --git a/internal/daemon/execution_engine_test.go b/internal/daemon/execution_engine_test.go index 7c316cbcf..c7d483771 100644 --- a/internal/daemon/execution_engine_test.go +++ b/internal/daemon/execution_engine_test.go @@ -144,7 +144,7 @@ func TestQuickJSCheckpointSurvivesDaemonRestart(t *testing.T) { t.Fatal(err) } owner, root, runtime := openPromptRuntime(t, store, result.RootID, llm.New("http://127.0.0.1:1", "key")) - if _, err := store.AdmitAgent(t.Context(), session.AgentAdmission{RootID: root.ID(), ParentAgentID: root.AgentID(), ChildAgentID: "child", Name: "child", Model: "model", Provider: "provider", CWD: root.meta.CWD}); err != nil { + if _, err := store.AdmitAgent(t.Context(), session.AgentAdmission{RootID: root.ID(), ParentAgentID: root.AgentID(), ChildAgentID: "child", Name: "child", Model: "model", Provider: "provider", CWD: root.WorkingDirectory()}); err != nil { t.Fatal(err) } if err := runtime.restoreChildren(t.Context()); err != nil { @@ -174,7 +174,7 @@ func TestExecutionEnginesPreserveExactStateCASAndMail(t *testing.T) { for _, engine := range []string{"starlark", "quickjs"} { t.Run(engine, func(t *testing.T) { store, root, runtime := openRecursiveRuntime(t, llm.New("http://127.0.0.1:1", "key"), 2, engine) - if _, err := store.AdmitAgent(t.Context(), session.AgentAdmission{RootID: root.ID(), ParentAgentID: root.AgentID(), ChildAgentID: "child", Name: "child", Model: "model", Provider: "provider", CWD: root.meta.CWD}); err != nil { + if _, err := store.AdmitAgent(t.Context(), session.AgentAdmission{RootID: root.ID(), ParentAgentID: root.AgentID(), ChildAgentID: "child", Name: "child", Model: "model", Provider: "provider", CWD: root.WorkingDirectory()}); err != nil { t.Fatal(err) } if err := runtime.restoreChildren(t.Context()); err != nil { diff --git a/internal/daemon/hooks.go b/internal/daemon/hooks.go index 7e355f7cd..11dc7317d 100644 --- a/internal/daemon/hooks.go +++ b/internal/daemon/hooks.go @@ -33,7 +33,7 @@ func (node *AgentSession) hookInvocation(ctx context.Context, hook *agentdef.Hoo turnID := node.turn.TurnID node.mu.Unlock() return hookInvocation{ - Definition: root.definition.ID, Revision: root.meta.DefinitionRevision, RootID: root.ID(), AgentID: node.id, TurnID: turnID, + Definition: root.definition.ID, Revision: root.definitionRevision, RootID: root.ID(), AgentID: node.id, TurnID: turnID, Hook: name, PermissionMode: mode, Timeout: hook.Timeout(), }, nil } diff --git a/internal/daemon/hooks_test.go b/internal/daemon/hooks_test.go index 36c1af67a..b245d16ab 100644 --- a/internal/daemon/hooks_test.go +++ b/internal/daemon/hooks_test.go @@ -306,7 +306,7 @@ func TestBeforeToolGatesEveryHostOperation(t *testing.T) { t.Fatalf("deny events = %+v", events) } // Rewrite: the rewritten path is what the files handler reads. - if err := os.WriteFile(filepath.Join(root.meta.CWD, "README.md"), []byte("hello readme"), 0o644); err != nil { + if err := os.WriteFile(filepath.Join(root.WorkingDirectory(), "README.md"), []byte("hello readme"), 0o644); err != nil { t.Fatal(err) } outcome = execCell(t.Context(), parent, `files.read(path="secret.env")`) diff --git a/internal/daemon/identity_test.go b/internal/daemon/identity_test.go index 6fb91f4a4..3c8b24676 100644 --- a/internal/daemon/identity_test.go +++ b/internal/daemon/identity_test.go @@ -101,7 +101,7 @@ func TestTrustedClientPermissionDecisionsAreScopedAndIdempotent(t *testing.T) { _, err = dispatcher.Dispatch(t.Context(), capability.Request{ RootID: rootID, AgentID: root.authority.AgentID, CapabilityID: root.authority.Files.ID, CapabilityGeneration: root.authority.Files.Generation, OperationID: "pending-operation", Operation: "write", - Arguments: json.RawMessage(`{}`), TraceID: "trace", WorkingDirectory: root.meta.CWD, + Arguments: json.RawMessage(`{}`), TraceID: "trace", WorkingDirectory: root.WorkingDirectory(), }) pending, ok := errors.AsType[*capability.PermissionPendingError](err) if !ok { @@ -150,7 +150,7 @@ func TestTrustedClientPermissionDecisionsAreScopedAndIdempotent(t *testing.T) { if _, err := competing.DecidePermission(t.Context(), decision); err == nil { t.Fatal("another client's command namespace reused a resolved permission") } - if _, err := os.Stat(filepath.Join(root.meta.CWD, "approved.txt")); !os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(root.WorkingDirectory(), "approved.txt")); !os.IsNotExist(err) { t.Fatalf("permission approval bypassed operation ownership: %v", err) } }) @@ -234,7 +234,7 @@ func TestRootSnapshotIsACompleteAuthoritativeClientView(t *testing.T) { _, err = dispatcher.Dispatch(t.Context(), capability.Request{ RootID: rootID, AgentID: root.authority.AgentID, CapabilityID: root.authority.Files.ID, CapabilityGeneration: root.authority.Files.Generation, OperationID: "snapshot-operation", Operation: "write", - Arguments: json.RawMessage(`{"secret":"` + secretArgument + `"}`), TraceID: "trace", WorkingDirectory: root.meta.CWD, + Arguments: json.RawMessage(`{"secret":"` + secretArgument + `"}`), TraceID: "trace", WorkingDirectory: root.WorkingDirectory(), }) var pending *capability.PermissionPendingError if !errors.As(err, &pending) { diff --git a/internal/daemon/input_test.go b/internal/daemon/input_test.go index 6573e2825..c8f466d95 100644 --- a/internal/daemon/input_test.go +++ b/internal/daemon/input_test.go @@ -177,7 +177,7 @@ func storeBackedInputSession(t *testing.T, workspace string) *AgentSession { } node := inputTestSession(t, workspace) node.agent.Vision = true - node.root = &Session{store: store, meta: sessionstore.Meta{ID: rootID}} + node.root = &Session{store: store, id: rootID} node.id = rootID node.authority = authority return node diff --git a/internal/daemon/metadata_routing_test.go b/internal/daemon/metadata_routing_test.go index 7cbc8eec1..01c1d195e 100644 --- a/internal/daemon/metadata_routing_test.go +++ b/internal/daemon/metadata_routing_test.go @@ -151,11 +151,10 @@ func TestOpenReloadsMetadataAfterRegistryPublication(t *testing.T) { if err != nil { t.Fatal(err) } - root, err := owner.openResolved(stale.ID) - if err != nil { + if _, err := owner.openResolved(stale.ID); err != nil { t.Fatal(err) } - if meta := <-constructed; meta.Title != "Cold rename" || root.meta.Title != meta.Title { - t.Fatalf("constructed stale metadata: factory=%q actor=%q", meta.Title, root.meta.Title) + if meta := <-constructed; meta.Title != "Cold rename" { + t.Fatalf("constructed stale metadata: factory=%q", meta.Title) } } diff --git a/internal/daemon/permission.go b/internal/daemon/permission.go index 6f5ae6a1b..a48b3392c 100644 --- a/internal/daemon/permission.go +++ b/internal/daemon/permission.go @@ -16,7 +16,7 @@ import ( // idempotency boundary as every other user action. func (s *Session) DecidePermissionCommand(ctx context.Context, command sessionstore.CommandAdmission, permissionID string, decision capability.Decision) (capability.Ticket, error) { command.Scope = sessionstore.CommandScopeRoot - command.RootID = s.meta.ID + command.RootID = s.id command.AgentID = s.authority.AgentID command.Kind = "permission.decide" command.Payload.Data = slices.Clone(command.Payload.Data) @@ -39,7 +39,7 @@ func (s *Session) DecidePermissionCommand(ctx context.Context, command sessionst if admitted.Command.Status == "queued" || admitted.Command.Status == "running" || admitted.Command.Status == "waiting" { return finish(errors.New("permission decision is still running")) } - body, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.meta.ID, admitted.Command.Outcome) + body, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.id, admitted.Command.Outcome) if resolveErr != nil { return finish(resolveErr) } @@ -49,7 +49,7 @@ func (s *Session) DecidePermissionCommand(ctx context.Context, command sessionst return finish(json.Unmarshal(body, &ticket)) } admission, decisionErr := s.store.Pending(actorCtx, permissionID) - if decisionErr == nil && admission.Request.RootID != s.meta.ID { + if decisionErr == nil && admission.Request.RootID != s.id { decisionErr = capability.ErrDenied } var rules []string @@ -132,7 +132,7 @@ func (s *Session) resolvePermission(ctx context.Context, admission capability.Ad // fails to resolve simply stays pending for the human. func (s *Session) rememberPermissionRules(ctx context.Context, permissionID, operation string, rules []string, decision capability.Decision) error { for _, rule := range rules { - if _, err := s.store.AddPermissionRule(ctx, s.meta.ID, operation, rule, decision.PrincipalID); err != nil { + if _, err := s.store.AddPermissionRule(ctx, s.id, operation, rule, decision.PrincipalID); err != nil { return err } } @@ -155,7 +155,7 @@ func (s *Session) rememberPermissionRules(ctx context.Context, permissionID, ope } s.store.SetGlobalPermissionRules(cfg.Permissions.Allow) } - pending, err := s.store.ListPendingPermissions(ctx, s.meta.ID) + pending, err := s.store.ListPendingPermissions(ctx, s.id) if err != nil { return err } @@ -176,7 +176,7 @@ func (s *Session) rememberPermissionRules(ctx context.Context, permissionID, ope if !ok { continue } - if source, err := s.store.PermissionRuleSource(ctx, s.meta.ID, operation, promptRules); err != nil || source == "" { + if source, err := s.store.PermissionRuleSource(ctx, s.id, operation, promptRules); err != nil || source == "" { continue } _, _ = s.resolvePermission(ctx, admission, prompt.ID, covered) @@ -200,7 +200,7 @@ func (s *Session) DecidePermission(ctx context.Context, permissionID string, dec if err != nil { return capability.Ticket{}, err } - if admission.Request.RootID != s.meta.ID { + if admission.Request.RootID != s.id { return capability.Ticket{}, capability.ErrDenied } return s.store.Decide(actorCtx, admission, permissionID, decision) @@ -210,7 +210,7 @@ func (s *Session) DecidePermission(ctx context.Context, permissionID string, dec func (s *Session) InspectPermission(ctx context.Context, permissionID string) (capability.Admission, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (capability.Admission, error) { admission, err := s.store.Pending(actorCtx, permissionID) - if err == nil && admission.Request.RootID != s.meta.ID { + if err == nil && admission.Request.RootID != s.id { return capability.Admission{}, capability.ErrDenied } return admission, err @@ -219,7 +219,7 @@ func (s *Session) InspectPermission(ctx context.Context, permissionID string) (c func (s *Session) InspectCapability(ctx context.Context, callerAgentID, capabilityID string) (sessionstore.CapabilityRecord, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.CapabilityRecord, error) { - return s.store.InspectCapability(actorCtx, s.meta.ID, callerAgentID, capabilityID) + return s.store.InspectCapability(actorCtx, s.id, callerAgentID, capabilityID) }) } @@ -228,7 +228,7 @@ func (s *Session) DelegateCapability(ctx context.Context, callerAgentID string, delegation.Scopes = slices.Clone(delegation.Scopes) delegation.MCP = slices.Clone(delegation.MCP) return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.CapabilityRecord, error) { - return s.store.DelegateCapability(actorCtx, s.meta.ID, callerAgentID, delegation) + return s.store.DelegateCapability(actorCtx, s.id, callerAgentID, delegation) }) } @@ -239,16 +239,16 @@ func (s *Session) RevokeCapability(ctx context.Context, callerAgentID, capabilit } func (s *Session) revokeCapability(ctx context.Context, callerAgentID, capabilityID string) (sessionstore.CapabilityRecord, error) { - pending, err := s.store.ListPendingPermissions(ctx, s.meta.ID) + pending, err := s.store.ListPendingPermissions(ctx, s.id) if err != nil { return sessionstore.CapabilityRecord{}, err } - record, err := s.store.RevokeCapabilityFor(ctx, s.meta.ID, callerAgentID, capabilityID) + record, err := s.store.RevokeCapabilityFor(ctx, s.id, callerAgentID, capabilityID) if err != nil { return record, err } if s.browserProviders != nil { - s.browserProviders.invalidateRevoked(ctx, s.meta.ID) + s.browserProviders.invalidateRevoked(ctx, s.id) } for _, prompt := range pending { if _, err := s.store.Pending(ctx, prompt.ID); !errors.Is(err, capability.ErrDenied) { diff --git a/internal/daemon/permission_mode_test.go b/internal/daemon/permission_mode_test.go index 23534a4ce..b657b6ff0 100644 --- a/internal/daemon/permission_mode_test.go +++ b/internal/daemon/permission_mode_test.go @@ -171,7 +171,7 @@ func assertResumedWritePermission(t *testing.T, store *session.Store, root *Sess t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) defer cancel() - path := filepath.Join(root.meta.CWD, "resumed.txt") + path := filepath.Join(root.WorkingDirectory(), "resumed.txt") arguments, err := json.Marshal(map[string]string{"path": path, "content": "resumed write"}) if err != nil { t.Fatal(err) diff --git a/internal/daemon/permission_test.go b/internal/daemon/permission_test.go index 9286ba51e..ba4376275 100644 --- a/internal/daemon/permission_test.go +++ b/internal/daemon/permission_test.go @@ -91,7 +91,7 @@ func TestDirectPermissionControlsStayRootScoped(t *testing.T) { _, err = dispatcher.Dispatch(t.Context(), capability.Request{ RootID: rootID, AgentID: root.AgentID(), CapabilityID: root.authority.Files.ID, CapabilityGeneration: root.authority.Files.Generation, OperationID: "direct-permission", Operation: "write", - Arguments: json.RawMessage(`{}`), TraceID: "trace", WorkingDirectory: root.meta.CWD, + Arguments: json.RawMessage(`{}`), TraceID: "trace", WorkingDirectory: root.WorkingDirectory(), }) var pending *capability.PermissionPendingError if !errors.As(err, &pending) { @@ -141,7 +141,7 @@ func TestPermissionRuleResolvesCoveredPromptsAndSkipsFutureOnes(t *testing.T) { RootID: rootID, AgentID: root.AgentID(), CapabilityID: root.authority.Shell.ID, CapabilityGeneration: root.authority.Shell.Generation, WriterCapabilityID: root.authority.Files.ID, WriterCapabilityGeneration: root.authority.Files.Generation, OperationID: operationID, Operation: "bash", - Arguments: json.RawMessage(`{"command":"` + command + `"}`), TraceID: "trace", WorkingDirectory: root.meta.CWD, + Arguments: json.RawMessage(`{"command":"` + command + `"}`), TraceID: "trace", WorkingDirectory: root.WorkingDirectory(), }) return response.Output, err } @@ -255,7 +255,7 @@ func TestPermissionRuleInExternalModeSkipsThePrimaryPrompt(t *testing.T) { RootID: rootID, AgentID: root.AgentID(), CapabilityID: root.authority.Shell.ID, CapabilityGeneration: root.authority.Shell.Generation, WriterCapabilityID: root.authority.Files.ID, WriterCapabilityGeneration: root.authority.Files.Generation, OperationID: operationID, Operation: "bash", - Arguments: json.RawMessage(`{"command":"` + command + `"}`), TraceID: "trace", WorkingDirectory: root.meta.CWD, + Arguments: json.RawMessage(`{"command":"` + command + `"}`), TraceID: "trace", WorkingDirectory: root.WorkingDirectory(), }) var pending *capability.PermissionPendingError if !errors.As(err, &pending) { diff --git a/internal/daemon/prompt.go b/internal/daemon/prompt.go index c98f21c33..c6643f476 100644 --- a/internal/daemon/prompt.go +++ b/internal/daemon/prompt.go @@ -77,8 +77,8 @@ func (session *AgentSession) executionEngine() string { if session.runtime != nil { return session.runtime.engine } - if session.root != nil && session.root.meta.ExecutionEngine != "" { - return session.root.meta.ExecutionEngine + if session.root != nil && session.root.engine != "" { + return session.root.engine } return rlm.EngineStarlark } diff --git a/internal/daemon/question.go b/internal/daemon/question.go index d6fac3c0d..a85f24be5 100644 --- a/internal/daemon/question.go +++ b/internal/daemon/question.go @@ -182,12 +182,12 @@ func (r *questionRegistry) openLocked() []sessionstore.LifecycleEvent { } func (s *Session) emitQuestionEvent(ctx context.Context, kind string, event sessionstore.LifecycleEvent) error { - event.RootID = s.meta.ID + event.RootID = s.id payload, err := json.Marshal(event) if err != nil { return err } - _, err = s.store.AppendRootEvent(ctx, s.meta.ID, kind, sessionstore.RuntimePayload{Data: payload, MediaType: "application/json", Source: "actor event"}) + _, err = s.store.AppendRootEvent(ctx, s.id, kind, sessionstore.RuntimePayload{Data: payload, MediaType: "application/json", Source: "actor event"}) return err } diff --git a/internal/daemon/recursive_runtime.go b/internal/daemon/recursive_runtime.go index 7fd577a7a..83fe6042f 100644 --- a/internal/daemon/recursive_runtime.go +++ b/internal/daemon/recursive_runtime.go @@ -269,9 +269,9 @@ func (runtime *RecursiveRuntime) Bind(ctx context.Context, root *Session) error runtime.mu.Unlock() return errors.New("recursive runtime is closed") } - if root.meta.ExecutionEngine != runtime.engine { + if root.engine != runtime.engine { runtime.mu.Unlock() - return fmt.Errorf("session execution engine %s does not match runtime %s", root.meta.ExecutionEngine, runtime.engine) + return fmt.Errorf("session execution engine %s does not match runtime %s", root.engine, runtime.engine) } runtime.root = root node := runtime.rootNode diff --git a/internal/daemon/recursive_state.go b/internal/daemon/recursive_state.go index f252e0bd4..719fbfee8 100644 --- a/internal/daemon/recursive_state.go +++ b/internal/daemon/recursive_state.go @@ -75,9 +75,9 @@ func (host *recursiveHost) statePage(ctx context.Context, operation string, argu node := host.session values, err := routeControlValue(node.root, ctx, func(actorCtx context.Context) ([]sessionstore.StateValue, error) { if operation == "private_list" { - return node.root.store.ListPrivateStatePage(actorCtx, node.root.meta.ID, node.id, afterKey, int(limit)+1) + return node.root.store.ListPrivateStatePage(actorCtx, node.root.id, node.id, afterKey, int(limit)+1) } - return node.root.store.BlackboardHistoryPage(actorCtx, node.root.meta.ID, node.id, key, afterVersion, int(limit)+1) + return node.root.store.BlackboardHistoryPage(actorCtx, node.root.id, node.id, key, afterVersion, int(limit)+1) }) if err != nil { return nil, err diff --git a/internal/daemon/rlm.go b/internal/daemon/rlm.go index d98b63b85..e99bfd820 100644 --- a/internal/daemon/rlm.go +++ b/internal/daemon/rlm.go @@ -14,7 +14,7 @@ import ( ) func (s *Session) AdmitAgent(ctx context.Context, admission sessionstore.AgentAdmission) error { - admission.RootID = s.meta.ID + admission.RootID = s.id _, err := routeControlOwnedValue(s, ctx, func(actorCtx context.Context) (int64, error) { return s.store.AdmitAgent(actorCtx, admission) }) @@ -24,13 +24,13 @@ func (s *Session) AdmitAgent(ctx context.Context, admission sessionstore.AgentAd // StartAgentTurn claims work only; the worker owns settlement before resolving input. func (s *Session) StartAgentTurn(ctx context.Context, agentID, turnID string) (sessionstore.AgentTurnStart, error) { return routeControlOwnedValue(s, ctx, func(actorCtx context.Context) (sessionstore.AgentTurnStart, error) { - return s.store.StartAgentTurn(actorCtx, s.meta.ID, agentID, turnID) + return s.store.StartAgentTurn(actorCtx, s.id, agentID, turnID) }) } func (s *Session) FinishAgentTurn(ctx context.Context, agentID string, commit sessionstore.AgentTurnCommit) error { _, err := routeControlOwnedValue(s, ctx, func(actorCtx context.Context) (struct{}, error) { - return struct{}{}, s.store.FinishAgentTurn(actorCtx, s.meta.ID, agentID, commit) + return struct{}{}, s.store.FinishAgentTurn(actorCtx, s.id, agentID, commit) }) return err } @@ -42,7 +42,7 @@ func (s *Session) SendMailboxMessage(ctx context.Context, senderAgentID, recipie var message sessionstore.MailboxMessage err := s.consumeBudgets(actorCtx, senderAgentID, durableReservations(len(send.Subject)+len(send.Body)), func() error { var err error - message, err = s.store.SendMailboxMessage(actorCtx, s.meta.ID, senderAgentID, recipientAgentID, send) + message, err = s.store.SendMailboxMessage(actorCtx, s.id, senderAgentID, recipientAgentID, send) return err }) if err == nil { @@ -54,7 +54,7 @@ func (s *Session) SendMailboxMessage(ctx context.Context, senderAgentID, recipie func (s *Session) ListMailboxMessages(ctx context.Context, agentID, status, sender string, limit int) ([]sessionstore.MailboxMessage, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.MailboxMessage, error) { - return s.store.ListMailboxMessages(actorCtx, s.meta.ID, agentID, status, sender, limit) + return s.store.ListMailboxMessages(actorCtx, s.id, agentID, status, sender, limit) }) } @@ -64,13 +64,13 @@ func (s *Session) ReadMailboxMessage(ctx context.Context, agentID, id string) (s body []byte } value, err := routeControlValue(s, ctx, func(actorCtx context.Context) (result, error) { - message, err := s.store.ReadMailboxMessage(actorCtx, s.meta.ID, agentID, id) + message, err := s.store.ReadMailboxMessage(actorCtx, s.id, agentID, id) if err != nil { return result{}, err } body := append([]byte(nil), message.Body.Inline...) if message.Body.ReferenceID != "" { - body, _, err = s.store.ReadContent(actorCtx, message.Body.ReferenceID, s.meta.ID, agentID, 0, sessionstore.MaxContentRead) + body, _, err = s.store.ReadContent(actorCtx, message.Body.ReferenceID, s.id, agentID, 0, sessionstore.MaxContentRead) } return result{message, body}, err }) @@ -80,7 +80,7 @@ func (s *Session) ReadMailboxMessage(ctx context.Context, agentID, id string) (s func (s *Session) CompleteMailboxMessages(ctx context.Context, agentID string, receipts []sessionstore.MailboxReceipt) (int64, error) { receipts = slices.Clone(receipts) return routeControlValue(s, ctx, func(actorCtx context.Context) (int64, error) { - return s.store.CompleteMailboxMessages(actorCtx, s.meta.ID, agentID, receipts) + return s.store.CompleteMailboxMessages(actorCtx, s.id, agentID, receipts) }) } @@ -89,7 +89,7 @@ func (s *Session) CompleteMailboxMessages(ctx context.Context, agentID string, r // daemon restarts first. func (s *Session) DeferMailboxMessage(ctx context.Context, agentID string, receipt sessionstore.MailboxReceipt, until time.Time) (int64, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (int64, error) { - revision, err := s.store.DeferMailboxMessage(actorCtx, s.meta.ID, agentID, receipt, until) + revision, err := s.store.DeferMailboxMessage(actorCtx, s.id, agentID, receipt, until) if err == nil { time.AfterFunc(max(time.Until(until), 0)+time.Second, func() { s.wakeAgent(agentID) }) } @@ -99,19 +99,19 @@ func (s *Session) DeferMailboxMessage(ctx context.Context, agentID string, recei func (s *Session) MailboxSummary(ctx context.Context, agentID string) (sessionstore.MailboxSummary, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.MailboxSummary, error) { - return s.store.MailboxSummary(actorCtx, s.meta.ID, agentID) + return s.store.MailboxSummary(actorCtx, s.id, agentID) }) } func (s *Session) ReadMailboxDigest(ctx context.Context, agentID string) (sessionstore.MailboxDigest, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.MailboxDigest, error) { - return s.store.ReadMailboxDigest(actorCtx, s.meta.ID, agentID, time.Now()) + return s.store.ReadMailboxDigest(actorCtx, s.id, agentID, time.Now()) }) } func (s *Session) AgentWorkStatus(ctx context.Context, agentID string) (sessionstore.AgentWork, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.AgentWork, error) { - return s.store.AgentWorkStatus(actorCtx, s.meta.ID, agentID, time.Now()) + return s.store.AgentWorkStatus(actorCtx, s.id, agentID, time.Now()) }) } @@ -123,13 +123,13 @@ func (s *Session) HasAgentWork(ctx context.Context, agentID string) (bool, error func (s *Session) ClaimSteers(ctx context.Context, agentID, turnID string) ([]sessionstore.InboxItem, error) { return routeControlOwnedValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.InboxItem, error) { - return s.store.ClaimSteers(actorCtx, s.meta.ID, agentID, turnID) + return s.store.ClaimSteers(actorCtx, s.id, agentID, turnID) }) } func (s *Session) RejectTurnInput(ctx context.Context, agentID, turnID string, seq int64, cause error) error { return s.routeControl(ctx, func(actorCtx context.Context) error { - if err := s.store.RejectTurnInput(actorCtx, s.meta.ID, agentID, turnID, seq, cause.Error()); err != nil { + if err := s.store.RejectTurnInput(actorCtx, s.id, agentID, turnID, seq, cause.Error()); err != nil { return err } if agentID == s.authority.AgentID { @@ -148,7 +148,7 @@ func (s *Session) SubmitAgentInput(ctx context.Context, callerAgentID, agentID, err := s.consumeBudgets(actorCtx, callerAgentID, durableReservations(len(text)), func() error { var err error sequence, err = s.store.EnqueueInbox(actorCtx, sessionstore.InboxEnqueue{ - RootID: s.meta.ID, AgentID: agentID, Kind: kind, + RootID: s.id, AgentID: agentID, Kind: kind, Payload: sessionstore.RuntimePayload{Data: []byte(text), MediaType: "text/plain", Source: source}, ParentSpanID: cause.SpanID, SpanTraceID: cause.TraceID, }) @@ -169,7 +169,7 @@ func (s *Session) LoadAgentScratch(ctx context.Context, agentID string) (string, manifest []byte } value, err := routeControlValue(s, ctx, func(actorCtx context.Context) (result, error) { - snapshot, manifest, err := s.store.LoadAgentScratch(actorCtx, s.meta.ID, agentID) + snapshot, manifest, err := s.store.LoadAgentScratch(actorCtx, s.id, agentID) return result{snapshot, manifest}, err }) return value.snapshot, value.manifest, err @@ -178,7 +178,7 @@ func (s *Session) LoadAgentScratch(ctx context.Context, agentID string) (string, func (s *Session) SaveAgentScratch(ctx context.Context, agentID, snapshot string, manifest []byte) error { manifest = slices.Clone(manifest) return s.routeControl(ctx, func(actorCtx context.Context) error { - return s.store.SaveAgentScratch(actorCtx, s.meta.ID, agentID, snapshot, manifest) + return s.store.SaveAgentScratch(actorCtx, s.id, agentID, snapshot, manifest) }) } @@ -190,7 +190,7 @@ func (s *Session) RecordScratchRestore(ctx context.Context, agentID string, repo notRestored = append(notRestored, sessionstore.ScratchSkip{Name: item.Name, Reason: item.Reason}) } return s.routeControl(ctx, func(actorCtx context.Context) error { - _, err := s.store.RecordScratchRestore(actorCtx, s.meta.ID, agentID, report.Restored, notRestored) + _, err := s.store.RecordScratchRestore(actorCtx, s.id, agentID, report.Restored, notRestored) return err }) } @@ -219,13 +219,13 @@ func (s *Session) reconcileAgentWork() { func (s *Session) LoadAgentTranscript(ctx context.Context, agentID string) ([]llm.Message, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]llm.Message, error) { - return s.store.LoadAgentTranscript(actorCtx, s.meta.ID, agentID) + return s.store.LoadAgentTranscript(actorCtx, s.id, agentID) }) } func (s *Session) LoadRetainedAgents(ctx context.Context) ([]sessionstore.RuntimeAgent, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.RuntimeAgent, error) { - return s.store.LoadRetainedAgents(actorCtx, s.meta.ID) + return s.store.LoadRetainedAgents(actorCtx, s.id) }) } @@ -235,7 +235,7 @@ func (s *Session) LoadAgentAuthority(ctx context.Context, agentID string) (capab names []string } value, err := routeControlValue(s, ctx, func(actorCtx context.Context) (result, error) { - authority, names, err := s.store.LoadAgentAuthority(actorCtx, s.meta.ID, agentID) + authority, names, err := s.store.LoadAgentAuthority(actorCtx, s.id, agentID) return result{authority, names}, err }) return value.authority, value.names, err @@ -243,13 +243,13 @@ func (s *Session) LoadAgentAuthority(ctx context.Context, agentID string) (capab func (s *Session) ListAgentRelatives(ctx context.Context, callerAgentID string) (sessionstore.AgentRelatives, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.AgentRelatives, error) { - return s.store.ListAgentRelatives(actorCtx, s.meta.ID, callerAgentID) + return s.store.ListAgentRelatives(actorCtx, s.id, callerAgentID) }) } func (s *Session) TerminalizeSubtree(ctx context.Context, callerAgentID, targetAgentID, status string) error { return s.routeControl(ctx, func(actorCtx context.Context) error { - _, err := s.store.TerminalizeSubtree(actorCtx, s.meta.ID, callerAgentID, targetAgentID, status) + _, err := s.store.TerminalizeSubtree(actorCtx, s.id, callerAgentID, targetAgentID, status) return err }) } @@ -267,7 +267,7 @@ func (s *Session) StoreContent(ctx context.Context, callerAgentID string, payloa var value sessionstore.RuntimeValue err := s.consumeBudgets(actorCtx, callerAgentID, durableReservations(len(payload.Data)), func() error { var err error - value, err = s.store.StoreContent(actorCtx, sessionstore.ContentGrant{RootID: s.meta.ID, AgentID: callerAgentID, Scope: sessionstore.ContentGrantAgent}, payload) + value, err = s.store.StoreContent(actorCtx, sessionstore.ContentGrant{RootID: s.id, AgentID: callerAgentID, Scope: sessionstore.ContentGrantAgent}, payload) return err }) return value, err @@ -280,7 +280,7 @@ func (s *Session) ReadContent(ctx context.Context, callerAgentID, referenceID st metadata sessionstore.ContentMetadata } value, err := routeControlValue(s, ctx, func(actorCtx context.Context) (result, error) { - body, metadata, err := s.store.ReadContent(actorCtx, referenceID, s.meta.ID, callerAgentID, offset, length) + body, metadata, err := s.store.ReadContent(actorCtx, referenceID, s.id, callerAgentID, offset, length) return result{body, metadata}, err }) return value.body, value.metadata, err @@ -292,7 +292,7 @@ func (s *Session) AddSchedule(ctx context.Context, expression, prompt string, an var id int err := s.consumeBudgets(actorCtx, s.authority.AgentID, reservations, func() error { var err error - id, err = s.store.AddSchedule(s.meta.ID, expression, prompt, anchor) + id, err = s.store.AddSchedule(s.id, expression, prompt, anchor) return err }) return id, err @@ -301,12 +301,12 @@ func (s *Session) AddSchedule(ctx context.Context, expression, prompt string, an func (s *Session) ListSchedules(ctx context.Context) ([]sessionstore.Schedule, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.Schedule, error) { - return s.store.SchedulesContext(actorCtx, s.meta.ID) + return s.store.SchedulesContext(actorCtx, s.id) }) } func (s *Session) CancelSchedule(ctx context.Context, id int) error { - return s.routeControl(ctx, func(context.Context) error { return s.store.DeleteSchedule(s.meta.ID, id) }) + return s.routeControl(ctx, func(context.Context) error { return s.store.DeleteSchedule(s.id, id) }) } func (s *Session) LaunchRuntimeWorker(kind string, work func()) bool { diff --git a/internal/daemon/scheduler.go b/internal/daemon/scheduler.go index 2cbfe7697..80fa85d5d 100644 --- a/internal/daemon/scheduler.go +++ b/internal/daemon/scheduler.go @@ -26,7 +26,7 @@ func (s *Session) startScheduler() { } func (s *Session) fireDueSchedules(at time.Time) error { - tasks, err := s.store.SchedulesContext(s.supervisor.ctx, s.meta.ID) + tasks, err := s.store.SchedulesContext(s.supervisor.ctx, s.id) if err != nil { return err } @@ -40,7 +40,7 @@ func (s *Session) fireDueSchedules(at time.Time) error { continue } _, err = s.store.ClaimScheduleFire(s.supervisor.ctx, session.ScheduleFireClaim{ - RootID: s.meta.ID, AgentID: s.authority.AgentID, ScheduleID: task.ID, + RootID: s.id, AgentID: s.authority.AgentID, ScheduleID: task.ID, ExpectedLastFire: task.LastFire, Slot: slot, }) if err != nil && !errors.Is(err, session.ErrScheduleClaimed) { diff --git a/internal/daemon/session.go b/internal/daemon/session.go index 6bbd17110..d125ee823 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -282,25 +282,34 @@ func (s *supervisor) wait() { } type Session struct { - titleChanged func(string) - providers *ProviderService - store *sessionstore.Store - meta sessionstore.Meta - authority capability.Authority - definition agentdef.Definition - executors *executorRegistry // custom tool executors; nil when no daemon owns the root - browserProviders *browserProviders - runner Runner - mcpMu sync.RWMutex - mcp Closeable - loadMCP func(context.Context) (mcp.Filtered, error) // guarded by mcpMu - mcpServers []string // definition filter, guarded by mcpMu - mcpGeneration uint64 // changes when the runtime/loader is replaced - runtime Closeable - factory Factory - supervisor *supervisor - mailbox chan inboxReady - done chan struct{} + titleChanged func(string) + providers *ProviderService + store *sessionstore.Store + // Identity is fixed for the root's lifetime. Saved facts (title, goal, + // archive state, directory) are read from the store when a decision needs + // them; nothing here mirrors the sessions row. + id string + kind sessionstore.SessionKind + engine string + definitionRevision string + // model, provider and effort are the installed runner's selection, assigned + // only when a runner is installed or its effort changes. + model, provider, effort string + authority capability.Authority + definition agentdef.Definition + executors *executorRegistry // custom tool executors; nil when no daemon owns the root + browserProviders *browserProviders + runner Runner + mcpMu sync.RWMutex + mcp Closeable + loadMCP func(context.Context) (mcp.Filtered, error) // guarded by mcpMu + mcpServers []string // definition filter, guarded by mcpMu + mcpGeneration uint64 // changes when the runtime/loader is replaced + runtime Closeable + factory Factory + supervisor *supervisor + mailbox chan inboxReady + done chan struct{} admitMu sync.RWMutex stopping bool @@ -352,7 +361,8 @@ func newSession(store *sessionstore.Store, meta sessionstore.Meta, authority cap goalMax = config.DefaultGoalMaxRounds } root := &Session{ - store: store, meta: meta, authority: authority, definition: effectiveDefinition(components), runner: components.Runner, mcp: components.MCP, loadMCP: components.LoadMCP, mcpServers: slices.Clone(effectiveDefinition(components).MCP.Servers), runtime: components.Runtime, + store: store, id: meta.ID, kind: meta.Kind, engine: meta.ExecutionEngine, definitionRevision: meta.DefinitionRevision, + model: meta.Model, provider: meta.Provider, effort: meta.Effort, authority: authority, definition: effectiveDefinition(components), runner: components.Runner, mcp: components.MCP, loadMCP: components.LoadMCP, mcpServers: slices.Clone(effectiveDefinition(components).MCP.Servers), runtime: components.Runtime, supervisor: newSupervisor(), mailbox: make(chan inboxReady, 1), done: make(chan struct{}), receipts: make(map[int64][]*Receipt), goalMax: goalMax, } @@ -362,10 +372,19 @@ func newSession(store *sessionstore.Store, meta sessionstore.Meta, authority cap return root } -func (s *Session) ID() string { return s.meta.ID } -func (s *Session) AgentID() string { return s.authority.AgentID } -func (s *Session) WorkingDirectory() string { return s.meta.CWD } -func (s *Session) Done() <-chan struct{} { return s.done } +func (s *Session) ID() string { return s.id } +func (s *Session) AgentID() string { return s.authority.AgentID } + +// WorkingDirectory is the saved directory from the sessions row. The +// installed runner owns the directory that commands actually run in. +func (s *Session) WorkingDirectory() string { + meta, err := s.store.LoadMeta(s.id) + if err != nil { + return "" + } + return meta.CWD +} +func (s *Session) Done() <-chan struct{} { return s.done } func (s *Session) Err() error { s.waitMu.Lock() @@ -375,11 +394,11 @@ func (s *Session) Err() error { // History reads only committed reconstruction state, never the live runner. func (s *Session) History() (sessionstore.Meta, []llm.Message, error) { - return s.store.Load(s.meta.ID) + return s.store.Load(s.id) } func (s *Session) Submit(ctx context.Context, text string) (*Receipt, error) { - if s.meta.Kind != sessionstore.SessionKindAgent { + if s.kind != sessionstore.SessionKindAgent { return nil, errors.New("tool-host sessions cannot submit model turns") } return routeControlValue(s, ctx, func(actorCtx context.Context) (*Receipt, error) { @@ -388,7 +407,7 @@ func (s *Session) Submit(ctx context.Context, text string) (*Receipt, error) { } func (s *Session) Steer(ctx context.Context, text string) (*Receipt, error) { - if s.meta.Kind != sessionstore.SessionKindAgent { + if s.kind != sessionstore.SessionKindAgent { return nil, errors.New("tool-host sessions cannot steer model turns") } return routeControlValue(s, ctx, func(actorCtx context.Context) (*Receipt, error) { @@ -410,7 +429,7 @@ func (s *Session) AcceptCommand(ctx context.Context, admission sessionstore.Comm func (s *Session) admitCommand(ctx context.Context, admission sessionstore.CommandAdmission, wait bool) (sessionstore.CommandAdmissionResult, *Receipt, error) { admission.Scope = sessionstore.CommandScopeRoot - admission.RootID = s.meta.ID + admission.RootID = s.id admission.AgentID = s.authority.AgentID admission.Payload.Data = slices.Clone(admission.Payload.Data) type admittedCommand struct { @@ -434,7 +453,7 @@ func (s *Session) admitCommand(ctx context.Context, admission sessionstore.Comma case "queued", "running", "waiting": s.register(receipt) case "succeeded", "failed", "cancelled", "interrupted": - output, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.meta.ID, result.Command.Outcome) + output, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.id, result.Command.Outcome) if resolveErr != nil { receipt.finish(Completion{Sequence: result.Command.IngressSeq, Err: resolveErr}) } else if result.Command.Status == "succeeded" { @@ -462,7 +481,7 @@ func (s *Session) Snapshot(ctx context.Context) (sessionstore.RootSnapshot, erro return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.RootSnapshot, error) { s.questions.mu.Lock() defer s.questions.mu.Unlock() - snapshot, err := s.store.SnapshotRoot(actorCtx, s.meta.ID) + snapshot, err := s.store.SnapshotRoot(actorCtx, s.id) if err == nil { snapshot.Questions = s.questions.openLocked() // in memory, not in the store: a mid-question client has no question.pending to replay } @@ -495,7 +514,7 @@ func (s *Session) enqueue(ctx context.Context, kind, text string, receipt bool) origin = "client" } sequence, err := s.store.EnqueueInbox(ctx, sessionstore.InboxEnqueue{ - RootID: s.meta.ID, AgentID: s.authority.AgentID, Kind: kind, Origin: origin, + RootID: s.id, AgentID: s.authority.AgentID, Kind: kind, Origin: origin, Payload: sessionstore.RuntimePayload{Data: []byte(text), MediaType: "text/plain", Source: kind}, }) if err != nil { @@ -647,7 +666,7 @@ func (s *Session) run() { if s.runtime != nil { cleanupErr = errors.Join(cleanupErr, safeClose("runtime", s.runtime.Close)) } - cleanupErr = errors.Join(cleanupErr, s.store.Processes().StopRoot(s.meta.ID)) + cleanupErr = errors.Join(cleanupErr, s.store.Processes().StopRoot(s.id)) // Settle control calls that were admitted before stopping. Some of those // callers are supervised workers, so waiting for workers first would leave // each side waiting on the other. @@ -657,13 +676,13 @@ func (s *Session) run() { // terminal recovery substitutes estimates for unresolved attempts. cleanupErr = errors.Join(cleanupErr, s.flushPendingAccounting()) if failed { - _, err := s.store.FailRoot(context.Background(), s.meta.ID, actorErr.Error()) + _, err := s.store.FailRoot(context.Background(), s.id, actorErr.Error()) cleanupErr = errors.Join(cleanupErr, err) } else if s.isTerminal() { - _, err := s.store.StopRoot(context.Background(), s.meta.ID, ErrStopped.Error()) + _, err := s.store.StopRoot(context.Background(), s.id, ErrStopped.Error()) cleanupErr = errors.Join(cleanupErr, err) } else { - _, err := s.store.InterruptRoot(context.Background(), s.meta.ID, ErrStopped.Error()) + _, err := s.store.InterruptRoot(context.Background(), s.id, ErrStopped.Error()) cleanupErr = errors.Join(cleanupErr, err) } if failed { @@ -826,7 +845,7 @@ func (s *Session) recordStreamEvent(stream *streamEnvelope) error { } if len(payload) > sessionstore.InlineValueLimit { value, err := s.store.StoreContent(s.supervisor.ctx, sessionstore.ContentGrant{ - RootID: s.meta.ID, Scope: sessionstore.ContentGrantRoot, + RootID: s.id, Scope: sessionstore.ContentGrantRoot, }, sessionstore.RuntimePayload{Data: payload, MediaType: "application/json", Source: stream.kind}) if err != nil { return err @@ -858,7 +877,7 @@ func (s *Session) recordStreamEvent(stream *streamEnvelope) error { return err } } - _, err = s.store.AppendRootEvent(s.supervisor.ctx, s.meta.ID, stream.kind, sessionstore.RuntimePayload{ + _, err = s.store.AppendRootEvent(s.supervisor.ctx, s.id, stream.kind, sessionstore.RuntimePayload{ Data: payload, MediaType: "application/json", Source: stream.kind, }) return err @@ -876,7 +895,7 @@ func (s *Session) dispatch() error { // The write lock excludes enqueue's read-locked publication window, so a // row is never claimed before its receipt is registered. s.admitMu.Lock() - items, err := s.store.LoadQueuedInbox(ctx, s.meta.ID, s.authority.AgentID, 0, 1) + items, err := s.store.LoadQueuedInbox(ctx, s.id, s.authority.AgentID, 0, 1) s.admitMu.Unlock() if err != nil { return err @@ -888,12 +907,12 @@ func (s *Session) dispatch() error { item := items[0] input = &item authored = item.Kind == "submit" || item.Kind == "submit.parts" || item.Kind == "steer" || item.Kind == "steer.parts" - if err := s.store.StartRootTurn(ctx, s.meta.ID, s.authority.AgentID, item.Seq); err != nil { + if err := s.store.StartRootTurn(ctx, s.id, s.authority.AgentID, item.Seq); err != nil { return err } current.seq = item.Seq } else { - work, err := s.store.AgentWorkStatus(ctx, s.meta.ID, s.authority.AgentID, time.Now()) + work, err := s.store.AgentWorkStatus(ctx, s.id, s.authority.AgentID, time.Now()) if err != nil { return err } @@ -901,10 +920,10 @@ func (s *Session) dispatch() error { s.scheduleDeferredWake(work.NextDeferredAt) return nil } - if blocked, err := s.store.RootMailboxNeedsInput(ctx, s.meta.ID, s.authority.AgentID); err != nil || blocked { + if blocked, err := s.store.RootMailboxNeedsInput(ctx, s.id, s.authority.AgentID); err != nil || blocked { return err } - turnID, err := s.store.StartRootMailboxTurn(ctx, s.meta.ID, s.authority.AgentID) + turnID, err := s.store.StartRootMailboxTurn(ctx, s.id, s.authority.AgentID) if err != nil { return err } @@ -1030,11 +1049,19 @@ func (s *Session) completeTurn(completion workerCompletion) error { } clearGoal := false goalContinuation := "" - if completion.err == nil && s.meta.Goal != "" && s.definition.Surface.GoalLoop { - if agent.GoalMet(completion.output) { - clearGoal = true - } else if s.goalRounds < s.goalMax { - goalContinuation = agent.GoalContinuePrompt(s.meta.Goal) + if completion.err == nil && s.definition.Surface.GoalLoop { + // The goal is a saved fact: goal.set, goal.run and goal.from-context + // write it to the store, so read it there at the decision boundary. + saved, err := s.store.LoadMeta(s.id) + if err != nil { + return err + } + if saved.Goal != "" { + if agent.GoalMet(completion.output) { + clearGoal = true + } else if s.goalRounds < s.goalMax { + goalContinuation = agent.GoalContinuePrompt(saved.Goal) + } } } outcome := completion.output @@ -1042,18 +1069,16 @@ func (s *Session) completeTurn(completion workerCompletion) error { outcome = completion.err.Error() } if err := s.store.CommitRootTurn(s.supervisor.ctx, sessionstore.RootTurnCommit{ - RootID: s.meta.ID, AgentID: s.authority.AgentID, InboxSeq: current.seq, TurnID: current.turnID, + RootID: s.id, AgentID: s.authority.AgentID, InboxSeq: current.seq, TurnID: current.turnID, AcknowledgedInbox: acknowledged, DeliveredMessages: completion.journal.DeliveredMessages, Messages: completion.journal.Messages, Compactions: journalCompactions(completion.journal), WorkspaceSeq: completion.workspaceSeq, WorkspaceRef: completion.workspaceRef, - ClearGoal: clearGoal, GoalContinuation: goalContinuation, - Model: s.meta.Model, Provider: s.meta.Provider, Status: status, Error: errorText, + ClearGoal: clearGoal, GoalContinuation: goalContinuation, Status: status, Error: errorText, Outcome: sessionstore.RuntimePayload{Data: encodeTurnOutcome(outcome, completion.journal.Output, completion.err), MediaType: "application/json", Source: "command outcome"}, }); err != nil { return err } if clearGoal { - s.meta.Goal = "" s.goalRounds = 0 } else if goalContinuation != "" { s.goalRounds++ @@ -1102,7 +1127,7 @@ func (s *Session) initializeTitle(initial *sessionstore.TitleInitialization) { ctx, cancel := context.WithTimeout(s.supervisor.ctx, 5*time.Second) defer cancel() if err := s.publishTitle(ctx, initial.Title); err != nil { - slog.Warn("publish initial session title", "root_id", s.meta.ID, "error", err) + slog.Warn("publish initial session title", "root_id", s.id, "error", err) } if !s.definition.Surface.AutoTitle || utf8.RuneCountInString(initial.Title) < 20 { return @@ -1146,30 +1171,29 @@ func (s *Session) completeTitle(work *titleWork) { s.titleWork = nil work.cancel() if work.err != nil { - slog.Warn("generate session title", "root_id", s.meta.ID, "error", work.err) + slog.Warn("generate session title", "root_id", s.id, "error", work.err) return } // Persistence has its own deadline, not the spent model-call deadline. ctx, cancel := context.WithTimeout(s.supervisor.ctx, 5*time.Second) defer cancel() - changed, err := s.store.SetTitleIfContext(ctx, s.meta.ID, work.placeholder, work.title) + changed, err := s.store.SetTitleIfContext(ctx, s.id, work.placeholder, work.title) if err == nil && changed { err = s.publishTitle(ctx, work.title) } if err != nil { - slog.Warn("save generated session title", "root_id", s.meta.ID, "error", err) + slog.Warn("save generated session title", "root_id", s.id, "error", err) } } // publishTitle is shared with manual rename; callers commit before publishing. func (s *Session) publishTitle(ctx context.Context, title string) error { - s.meta.Title = title - s.notifyTitleChanged(s.meta.ID) + s.notifyTitleChanged(s.id) payload, err := json.Marshal(SessionUpdateEvent{Title: title}) if err != nil { return err } - _, err = s.store.AppendRootEvent(ctx, s.meta.ID, "session.title.updated", sessionstore.RuntimePayload{ + _, err = s.store.AppendRootEvent(ctx, s.id, "session.title.updated", sessionstore.RuntimePayload{ Data: payload, MediaType: "application/json", Source: "session.title.updated", }) return err diff --git a/internal/daemon/session_state_ownership_test.go b/internal/daemon/session_state_ownership_test.go new file mode 100644 index 000000000..b4ec67c53 --- /dev/null +++ b/internal/daemon/session_state_ownership_test.go @@ -0,0 +1,127 @@ +package daemon + +import ( + "context" + "database/sql" + "encoding/json" + "path/filepath" + "strings" + "testing" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/session" +) + +// A rejected effort save must leave the runner, the saved row and every +// reader at the previous level: the store is the authority, so it is written +// before the runner is touched. +func TestEffortPersistsBeforeItApplies(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}} + value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: runner}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = value.Close() }) + root, err := value.Open(rootID) + if err != nil { + t.Fatal(err) + } + if result := clientCommand(t, root, "tui", "effort-high", "session.effort", map[string]any{"effort": "high"}); result.Status != "succeeded" || runner.effort != "high" { + t.Fatalf("initial effort = %+v runner=%q", result, runner.effort) + } + + db, err := sql.Open("sqlite", path) + if err != nil { + t.Fatal(err) + } + defer db.Close() + if _, err := db.ExecContext(t.Context(), `CREATE TRIGGER reject_effort BEFORE UPDATE OF effort ON sessions + BEGIN SELECT RAISE(ABORT,'effort rejected'); END`); err != nil { + t.Fatal(err) + } + result := clientCommand(t, root, "tui", "effort-low", "session.effort", map[string]any{"effort": "low"}) + if result.Status != "failed" || !strings.Contains(result.Error, "effort rejected") { + t.Fatalf("rejected effort = %+v", result) + } + meta, _, err := store.Load(rootID) + if err != nil { + t.Fatal(err) + } + get := clientCommand(t, root, "tui", "effort-get", "session.effort.get", map[string]any{}) + if runner.effort != "high" || meta.Effort != "high" || get.Output != "high" { + t.Fatalf("failed save changed effort: runner=%q saved=%q get=%+v", runner.effort, meta.Effort, get) + } +} + +type blockingGoalRunner struct { + *fakeRunner + started, release chan struct{} +} + +func (r *blockingGoalRunner) FormGoal(context.Context, int) (string, llm.Usage, error) { + close(r.started) + <-r.release + return "formulated goal", llm.Usage{}, nil +} + +// goal.set and goal.run share the busy guard with effort, model and workspace, +// so a goal formulation cannot be overwritten by, or overwrite, a concurrent +// explicit goal. +func TestGoalCommandsRefuseWhileGoalFormulationRuns(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + runner := &blockingGoalRunner{ + fakeRunner: &fakeRunner{turn: func(context.Context, string, bool) (string, error) { return "GOAL_MET — verified", nil }}, + started: make(chan struct{}), release: make(chan struct{}), + } + value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: runner}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = value.Close() }) + root, err := value.Open(rootID) + if err != nil { + t.Fatal(err) + } + + type outcome struct { + result CommandResult + err error + } + done := make(chan outcome, 1) + go func() { + raw, _ := json.Marshal(map[string]any{"window": 4}) + digest, err := requestDigest("root", root.ID(), "goal.from-context", raw) + if err != nil { + done <- outcome{err: err} + return + } + result, err := root.ClientCommand(context.Background(), session.CommandAdmission{ + ClientID: "tui", CommandID: "goal-context", RequestDigest: digest, + Payload: session.RuntimePayload{Data: raw, MediaType: "application/json", Source: "goal.from-context"}, + }, "goal.from-context", raw) + done <- outcome{result: result, err: err} + }() + <-runner.started + set := clientCommand(t, root, "tui", "goal-set-during", "goal.set", map[string]any{"text": "user goal"}) + if set.Status != "failed" || !strings.Contains(set.Error, "goal cannot change") { + t.Fatalf("goal.set during formulation = %+v", set) + } + close(runner.release) + formed := <-done + if formed.err != nil || formed.result.Status != "succeeded" || formed.result.Output != "formulated goal" { + t.Fatalf("formulation = %+v %v", formed.result, formed.err) + } + meta, _, err := store.Load(rootID) + if err != nil || meta.Goal != "formulated goal" { + t.Fatalf("saved goal = %q %v", meta.Goal, err) + } +} diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index 4d682c145..f23d760da 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -880,7 +880,7 @@ func TestOpenBindsMCPProcesses(t *testing.T) { if err != nil { t.Fatal(err) } - if manager.processes != store.Processes() || manager.rootID != rootID || manager.cwd != root.meta.CWD { + if manager.processes != store.Processes() || manager.rootID != rootID || manager.cwd != root.WorkingDirectory() { t.Fatalf("MCP process scope=%p %q %q", manager.processes, manager.rootID, manager.cwd) } if len(ag.AllTools()) != 0 { diff --git a/internal/daemon/spans.go b/internal/daemon/spans.go index a1f529f43..b42641962 100644 --- a/internal/daemon/spans.go +++ b/internal/daemon/spans.go @@ -253,8 +253,8 @@ func (s *Session) modelCallSpanStart(agentID, callID string, attempt llm.ModelAt maps.Copy(attrs, runtime.PromptAttrs(agentID, attempt.Purpose)) } s.recordSpanStart(sessionstore.SpanRecord{ - ID: sessionstore.ModelCallSpanID(s.meta.ID, callID), TraceID: turn.TraceID, ParentID: turn.SpanID, - RootID: s.meta.ID, AgentID: agentID, TurnID: turnID, + ID: sessionstore.ModelCallSpanID(s.id, callID), TraceID: turn.TraceID, ParentID: turn.SpanID, + RootID: s.id, AgentID: agentID, TurnID: turnID, Kind: sessionstore.SpanKindLLM, Name: modelCallSpanName(attempt), Status: sessionstore.SpanStatusRunning, StartNS: startedAt.UnixNano(), Attrs: sessionstore.SpanAttrs(attrs), }) @@ -451,8 +451,8 @@ func (s *Session) modelCallSpanEnd(agentID, callID string, attempt llm.ModelAtte status = sessionstore.SpanStatusInterrupted } s.recordSpanEnd(sessionstore.SpanRecord{ - ID: sessionstore.ModelCallSpanID(s.meta.ID, callID), TraceID: turn.TraceID, ParentID: turn.SpanID, - RootID: s.meta.ID, AgentID: agentID, TurnID: turnID, + ID: sessionstore.ModelCallSpanID(s.id, callID), TraceID: turn.TraceID, ParentID: turn.SpanID, + RootID: s.id, AgentID: agentID, TurnID: turnID, Kind: sessionstore.SpanKindLLM, Name: modelCallSpanName(attempt), Status: status, EndNS: time.Now().UnixNano(), Attrs: sessionstore.SpanAttrs(attrs), }) if runtime, has := s.runtime.(interface{ NoteModelCall(string, string) }); has { @@ -468,8 +468,8 @@ func (s *Session) questionSpanStart(agentID, questionID, question string) { return } s.recordSpanStart(sessionstore.SpanRecord{ - ID: sessionstore.WaitSpanID(s.meta.ID, questionID), TraceID: turn.TraceID, ParentID: turn.SpanID, - RootID: s.meta.ID, AgentID: agentID, TurnID: turnID, + ID: sessionstore.WaitSpanID(s.id, questionID), TraceID: turn.TraceID, ParentID: turn.SpanID, + RootID: s.id, AgentID: agentID, TurnID: turnID, Kind: sessionstore.SpanKindWait, Name: "question", Status: sessionstore.SpanStatusRunning, StartNS: time.Now().UnixNano(), Attrs: sessionstore.SpanAttrs(map[string]any{"question_id": questionID, "input": sessionstore.SpanExcerpt(question)}), }) @@ -485,8 +485,8 @@ func (s *Session) questionSpanEnd(agentID, questionID, outcome string, closed bo status = sessionstore.SpanStatusCancelled } s.recordSpanEnd(sessionstore.SpanRecord{ - ID: sessionstore.WaitSpanID(s.meta.ID, questionID), TraceID: turn.TraceID, ParentID: turn.SpanID, - RootID: s.meta.ID, AgentID: agentID, TurnID: turnID, + ID: sessionstore.WaitSpanID(s.id, questionID), TraceID: turn.TraceID, ParentID: turn.SpanID, + RootID: s.id, AgentID: agentID, TurnID: turnID, Kind: sessionstore.SpanKindWait, Name: "question", Status: status, EndNS: time.Now().UnixNano(), Attrs: sessionstore.SpanAttrs(map[string]any{"output": sessionstore.SpanExcerpt(outcome)}), }) diff --git a/internal/daemon/state.go b/internal/daemon/state.go index 9d3879856..5cd5fc300 100644 --- a/internal/daemon/state.go +++ b/internal/daemon/state.go @@ -23,43 +23,43 @@ func (s *Session) mutateState(ctx context.Context, callerAgentID string, payload func (s *Session) GetPrivateState(ctx context.Context, callerAgentID, key string) (sessionstore.StateValue, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.StateValue, error) { - return s.store.GetPrivateState(actorCtx, s.meta.ID, callerAgentID, key) + return s.store.GetPrivateState(actorCtx, s.id, callerAgentID, key) }) } func (s *Session) ListPrivateState(ctx context.Context, callerAgentID string) ([]sessionstore.StateValue, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.StateValue, error) { - return s.store.ListPrivateState(actorCtx, s.meta.ID, callerAgentID) + return s.store.ListPrivateState(actorCtx, s.id, callerAgentID) }) } func (s *Session) SetPrivateState(ctx context.Context, callerAgentID, key string, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - return s.store.SetPrivateState(actorCtx, s.meta.ID, callerAgentID, key, payload) + return s.store.SetPrivateState(actorCtx, s.id, callerAgentID, key, payload) }) } func (s *Session) AppendPrivateState(ctx context.Context, callerAgentID, key string, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - return s.store.AppendPrivateState(actorCtx, s.meta.ID, callerAgentID, key, payload) + return s.store.AppendPrivateState(actorCtx, s.id, callerAgentID, key, payload) }) } func (s *Session) CompareAndSwapPrivateState(ctx context.Context, callerAgentID, key string, expectedVersion int64, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - return s.store.CompareAndSwapPrivateState(actorCtx, s.meta.ID, callerAgentID, key, expectedVersion, payload) + return s.store.CompareAndSwapPrivateState(actorCtx, s.id, callerAgentID, key, expectedVersion, payload) }) } func (s *Session) GetBlackboard(ctx context.Context, callerAgentID, key string) (sessionstore.StateValue, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) (sessionstore.StateValue, error) { - return s.store.GetBlackboard(actorCtx, s.meta.ID, callerAgentID, key) + return s.store.GetBlackboard(actorCtx, s.id, callerAgentID, key) }) } func (s *Session) SetBlackboard(ctx context.Context, callerAgentID, key string, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - value, err := s.store.SetBlackboard(actorCtx, s.meta.ID, callerAgentID, key, payload) + value, err := s.store.SetBlackboard(actorCtx, s.id, callerAgentID, key, payload) if err == nil { s.wakeSubscribers(key) } @@ -69,7 +69,7 @@ func (s *Session) SetBlackboard(ctx context.Context, callerAgentID, key string, func (s *Session) AppendBlackboard(ctx context.Context, callerAgentID, key string, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - value, err := s.store.AppendBlackboard(actorCtx, s.meta.ID, callerAgentID, key, payload) + value, err := s.store.AppendBlackboard(actorCtx, s.id, callerAgentID, key, payload) if err == nil { s.wakeSubscribers(key) } @@ -79,7 +79,7 @@ func (s *Session) AppendBlackboard(ctx context.Context, callerAgentID, key strin func (s *Session) CompareAndSwapBlackboard(ctx context.Context, callerAgentID, key string, expectedVersion int64, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { return s.mutateState(ctx, callerAgentID, payload, func(actorCtx context.Context, payload sessionstore.RuntimePayload) (sessionstore.StateValue, error) { - value, err := s.store.CompareAndSwapBlackboard(actorCtx, s.meta.ID, callerAgentID, key, expectedVersion, payload) + value, err := s.store.CompareAndSwapBlackboard(actorCtx, s.id, callerAgentID, key, expectedVersion, payload) if err == nil { s.wakeSubscribers(key) } @@ -91,7 +91,7 @@ func (s *Session) CompareAndSwapBlackboard(ctx context.Context, callerAgentID, k // row was committed with the mutation; the durable inbox is the truth and a // spurious wake is harmless. func (s *Session) wakeSubscribers(key string) { - ids, err := s.store.SubscribedAgents(context.Background(), s.meta.ID, key) + ids, err := s.store.SubscribedAgents(context.Background(), s.id, key) if err != nil { return } @@ -102,7 +102,7 @@ func (s *Session) wakeSubscribers(key string) { func (s *Session) BlackboardHistory(ctx context.Context, callerAgentID, key string) ([]sessionstore.StateValue, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.StateValue, error) { - return s.store.BlackboardHistory(actorCtx, s.meta.ID, callerAgentID, key) + return s.store.BlackboardHistory(actorCtx, s.id, callerAgentID, key) }) } @@ -114,7 +114,7 @@ func (s *Session) CreateBlackboardSubscription(ctx context.Context, callerAgentI var subscription sessionstore.BlackboardSubscription err := s.consumeBudgets(actorCtx, callerAgentID, reservations, func() error { var err error - subscription, err = s.store.CreateBlackboardSubscription(actorCtx, s.meta.ID, callerAgentID, key) + subscription, err = s.store.CreateBlackboardSubscription(actorCtx, s.id, callerAgentID, key) return err }) return subscription, err @@ -123,12 +123,12 @@ func (s *Session) CreateBlackboardSubscription(ctx context.Context, callerAgentI func (s *Session) ListBlackboardSubscriptions(ctx context.Context, callerAgentID string) ([]sessionstore.BlackboardSubscription, error) { return routeControlValue(s, ctx, func(actorCtx context.Context) ([]sessionstore.BlackboardSubscription, error) { - return s.store.ListBlackboardSubscriptions(actorCtx, s.meta.ID, callerAgentID) + return s.store.ListBlackboardSubscriptions(actorCtx, s.id, callerAgentID) }) } func (s *Session) CancelBlackboardSubscription(ctx context.Context, callerAgentID, subscriptionID string) error { return s.routeControl(ctx, func(actorCtx context.Context) error { - return s.store.CancelBlackboardSubscription(actorCtx, s.meta.ID, callerAgentID, subscriptionID) + return s.store.CancelBlackboardSubscription(actorCtx, s.id, callerAgentID, subscriptionID) }) } diff --git a/internal/daemon/v2_event_schema_test.go b/internal/daemon/v2_event_schema_test.go index 7b760f67b..c6d189d33 100644 --- a/internal/daemon/v2_event_schema_test.go +++ b/internal/daemon/v2_event_schema_test.go @@ -137,7 +137,7 @@ func TestV2ReferencedEventPayloadMatchesSchema(t *testing.T) { func TestV2LargeStreamEventsPreserveCallIdentity(t *testing.T) { fixture := newV2Fixture(t, &fakeRunner{}) - root := &Session{store: fixture.store, meta: session.Meta{ID: fixture.rootID}, supervisor: newSupervisor()} + root := &Session{store: fixture.store, id: fixture.rootID, supervisor: newSupervisor()} defer root.supervisor.cancel() for _, kind := range []string{"stream.tool.call", "stream.tool.started", "stream.tool.completed"} { event := StreamEvent{AgentID: "child", TurnID: "child:turn:1", ID: "call-1", Name: "rlm_exec"} diff --git a/internal/daemon/v2_sdk_repl_test.go b/internal/daemon/v2_sdk_repl_test.go index 6f6bf3d97..43a06d1d6 100644 --- a/internal/daemon/v2_sdk_repl_test.go +++ b/internal/daemon/v2_sdk_repl_test.go @@ -207,7 +207,7 @@ func registerSDKREPLProbes(mux *http.ServeMux, store *session.Store, rootID stri for _, event := range events { if strings.HasPrefix(r.PathValue("step"), "activity-large") { if payload, ok := event.payload.(StreamEvent); ok { - root := &Session{store: store, meta: session.Meta{ID: rootID}, supervisor: newSupervisor()} + root := &Session{store: store, id: rootID, supervisor: newSupervisor()} err := root.recordStreamEvent(&streamEnvelope{kind: event.kind, event: payload}) root.supervisor.cancel() if err != nil { diff --git a/internal/daemon/view.go b/internal/daemon/view.go index b34064585..ebc25f73d 100644 --- a/internal/daemon/view.go +++ b/internal/daemon/view.go @@ -14,7 +14,7 @@ func (s *Session) SnapshotView(ctx context.Context) (session.RootSnapshot, error return routeControlValue(s, ctx, func(actorCtx context.Context) (session.RootSnapshot, error) { s.questions.mu.Lock() defer s.questions.mu.Unlock() - snapshot, err := s.store.SnapshotRootView(actorCtx, s.meta.ID, session.SnapshotViewOptions{RecentMessages: 64, CollectionLimit: 128, MaxBytes: 384 << 10}) + snapshot, err := s.store.SnapshotRootView(actorCtx, s.id, session.SnapshotViewOptions{RecentMessages: 64, CollectionLimit: 128, MaxBytes: 384 << 10}) if err != nil { return snapshot, err } diff --git a/internal/session/command_test.go b/internal/session/command_test.go index 7c9c99f29..b0103cab2 100644 --- a/internal/session/command_test.go +++ b/internal/session/command_test.go @@ -167,7 +167,7 @@ func TestRootTurnCommitsProtocolCommandOutcome(t *testing.T) { outcome := bytes.Repeat([]byte("result"), 2048) if err := st.CommitRootTurn(context.Background(), RootTurnCommit{ RootID: rootID, AgentID: authority.AgentID, InboxSeq: result.Command.IngressSeq, - Model: "model", Provider: "provider", Outcome: RuntimePayload{Data: outcome, Source: "outcome"}, + Outcome: RuntimePayload{Data: outcome, Source: "outcome"}, }); err != nil { t.Fatal(err) } diff --git a/internal/session/input_lifecycle_test.go b/internal/session/input_lifecycle_test.go index 7bdb0feb9..a03f11885 100644 --- a/internal/session/input_lifecycle_test.go +++ b/internal/session/input_lifecycle_test.go @@ -112,7 +112,6 @@ func TestRootInputRecoveryPreservesOnlyUnclaimedModelCommands(t *testing.T) { t.Fatal(err) } if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ - Model: "model", Provider: "provider", RootID: rootID, AgentID: rootAgentID, InboxSeq: command.Command.IngressSeq, Messages: []llm.Message{{Role: "assistant", Content: "finished " + command.Command.CommandID}}, Outcome: RuntimePayload{Data: []byte("finished")}, @@ -294,7 +293,6 @@ func TestClaimSteersRequiresExactActiveTurnAndRollsBackBatch(t *testing.T) { t.Fatalf("duplicate boundary claim = %+v, %v", more, err) } if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ - Model: "model", Provider: "provider", RootID: rootID, AgentID: rootAgentID, InboxSeq: initial.Command.IngressSeq, AcknowledgedInbox: []int64{first.Command.IngressSeq, second.Command.IngressSeq}, }); err != nil { @@ -380,7 +378,6 @@ func TestRejectTurnInputSettlesInvalidSteerWithoutFailingTurn(t *testing.T) { t.Fatalf("duplicate rejection = %v", err) } if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ - Model: "model", Provider: "provider", RootID: rootID, AgentID: rootAgentID, InboxSeq: initial.Command.IngressSeq, Messages: []llm.Message{{Role: "assistant", Content: "valid work completed"}}, }); err != nil { @@ -408,7 +405,7 @@ func TestRootCommitSettlesUnacknowledgedSteerClaimsOnly(t *testing.T) { queued := inputTestCommand(t, store, rootID, rootAgentID, "unclaimed", "steer") if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ RootID: rootID, AgentID: rootAgentID, InboxSeq: initial.Command.IngressSeq, - Status: status, Model: "model", Provider: "provider", + Status: status, }); err != nil { t.Fatal(err) } @@ -465,8 +462,8 @@ func TestTurnCommitRejectsUnclaimedAndStaleInboxAcknowledgements(t *testing.T) { if recipient == "root" { err = store.CommitRootTurn(t.Context(), RootTurnCommit{ RootID: rootID, AgentID: agentID, InboxSeq: initial.InboxSeq, - AcknowledgedInbox: []int64{acknowledged}, Model: "model", Provider: "provider", - Messages: []llm.Message{{Role: "assistant", Content: "must not persist"}}, + AcknowledgedInbox: []int64{acknowledged}, + Messages: []llm.Message{{Role: "assistant", Content: "must not persist"}}, }) } else { err = store.FinishAgentTurn(t.Context(), rootID, agentID, AgentTurnCommit{ @@ -503,7 +500,7 @@ func TestRootTurnCommitRequiresCorrelatedCommandStillRunning(t *testing.T) { before := inputRootSnapshot(t, store, rootID) if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ RootID: rootID, AgentID: rootAgentID, InboxSeq: command.Command.IngressSeq, - Model: "model", Provider: "provider", Outcome: RuntimePayload{Data: []byte("must not persist")}, + Outcome: RuntimePayload{Data: []byte("must not persist")}, }); err == nil { t.Fatal("turn completed a command that was not running") } @@ -582,7 +579,6 @@ func TestCorruptInputIsClaimedAndSettledWithoutStrandingAgent(t *testing.T) { if recipient == "root" { err = store.CommitRootTurn(t.Context(), RootTurnCommit{ RootID: rootID, AgentID: agentID, InboxSeq: seq, Status: status, - Model: "model", Provider: "provider", }) } else { var acknowledged []int64 diff --git a/internal/session/otlp_export_test.go b/internal/session/otlp_export_test.go index 4cc88592b..2919361de 100644 --- a/internal/session/otlp_export_test.go +++ b/internal/session/otlp_export_test.go @@ -154,7 +154,7 @@ func TestExportOTLPCarriesEveryMessageOnceAndKeepsCostHonest(t *testing.T) { insertTranscriptRow(t, store, root, 2, map[string]any{"role": "assistant", "content": "", "call_id": "c1", "tool_calls": []map[string]any{{"id": "tc1", "type": "function", "function": map[string]any{"name": "rlm_exec", "arguments": `{"code":"print(files.read(\"README.md\"))"}`}}}}) insertTranscriptRow(t, store, root, 3, map[string]any{"role": "tool", "tool_call_id": "tc1", "name": "rlm_exec", "content": "# Whip"}) insertTranscriptRow(t, store, root, 4, map[string]any{"role": "assistant", "content": "Done.", "call_id": "c2"}) - must(store.CommitRootTurn(context.Background(), RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Messages: []llm.Message{{Role: "assistant", Content: "Done."}}, Model: "kimi-k3-fast", Provider: "inference-net"})) + must(store.CommitRootTurn(context.Background(), RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Messages: []llm.Message{{Role: "assistant", Content: "Done."}}})) data, summary, err := store.ExportOTLP(context.Background(), root, ExportOptions{ServiceVersion: "test"}) if err != nil { @@ -508,7 +508,7 @@ func TestExportOTLPEmitsPromptsAndCompaction(t *testing.T) { insertTranscriptRow(t, store, root, 2, map[string]any{"role": "assistant", "content": "Reading.", "call_id": "c1"}) insertTranscriptRow(t, store, root, 3, map[string]any{"role": "user", "content": "continue"}) insertTranscriptRow(t, store, root, 4, map[string]any{"role": "assistant", "content": "Done.", "call_id": "c2"}) - must(store.CommitRootTurn(ctx, RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq1, Model: "kimi-k3-fast", Provider: "inference-net"})) + must(store.CommitRootTurn(ctx, RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq1})) // The next turn composed a different prompt and a different notice, so // its first call carries both again. changed := intern("prompt.system", "You are the root agent. Skill: docs.") diff --git a/internal/session/runtime.go b/internal/session/runtime.go index 787ad4755..9458ea943 100644 --- a/internal/session/runtime.go +++ b/internal/session/runtime.go @@ -265,8 +265,6 @@ type RootTurnCommit struct { WorkspaceRef string ClearGoal bool GoalContinuation string - Model string - Provider string Status string Error string Outcome RuntimePayload @@ -730,8 +728,7 @@ func (s *Store) commitRootTurn(ctx context.Context, commit RootTurnCommit, befor return err } } - if _, err := tx.ExecContext(ctx, `UPDATE sessions SET updated_at=?,model=?,provider=? WHERE id=?`, - stamp, commit.Model, commit.Provider, commit.RootID); err != nil { + if _, err := tx.ExecContext(ctx, `UPDATE sessions SET updated_at=? WHERE id=?`, stamp, commit.RootID); err != nil { return err } if status == "succeeded" { diff --git a/internal/session/runtime_storage_test.go b/internal/session/runtime_storage_test.go index 0e7b0cb3b..e42b8cfe0 100644 --- a/internal/session/runtime_storage_test.go +++ b/internal/session/runtime_storage_test.go @@ -182,7 +182,7 @@ func TestRootTurnCommitWriteFailuresPreserveHumanInputAndHistory(t *testing.T) { {"raw history", "INSERT", "messages", "", false}, {"compaction", "INSERT", "compactions", "", false}, {"workspace snapshot", "INSERT", "snapshots", "", false}, - {"session metadata", "UPDATE", "sessions", "NEW.model='new-model'", false}, + {"session metadata", "UPDATE", "sessions", "", false}, {"goal continuation", "INSERT", "inbox", "NEW.kind='goal'", false}, {"goal event", "INSERT", "events", "NEW.kind='goal.continued'", false}, {"clear goal", "UPDATE", "sessions", "NEW.goal='' AND OLD.goal<>''", true}, @@ -202,7 +202,7 @@ func TestRootTurnCommitWriteFailuresPreserveHumanInputAndHistory(t *testing.T) { t.Fatal(err) } before := inputRootSnapshot(t, store, root) - commit := RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Status: "succeeded", Model: "new-model", Provider: "new-provider", Messages: []llm.Message{{Role: "assistant", Content: "research result"}}, Compactions: []RootCompaction{{Summary: "summary", RawCutoff: new(1)}}, WorkspaceRef: "workspace-snapshot", WorkspaceSeq: 1, GoalContinuation: "continue research"} + commit := RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Status: "succeeded", Messages: []llm.Message{{Role: "assistant", Content: "research result"}}, Compactions: []RootCompaction{{Summary: "summary", RawCutoff: new(1)}}, WorkspaceRef: "workspace-snapshot", WorkspaceSeq: 1, GoalContinuation: "continue research"} if failure.clearGoal { commit.ClearGoal = true commit.GoalContinuation = "" @@ -341,7 +341,7 @@ func TestArtifactDirectoryFailureCannotPublishUnrecoverableWork(t *testing.T) { _, err := store.ClaimScheduleFire(t.Context(), ScheduleFireClaim{RootID: root, AgentID: root, ScheduleID: scheduleID, Slot: anchor}) return err default: - commit := RootTurnCommit{RootID: root, AgentID: root, InboxSeq: command.Command.IngressSeq, Status: "succeeded", Model: "model", Provider: "provider"} + commit := RootTurnCommit{RootID: root, AgentID: root, InboxSeq: command.Command.IngressSeq, Status: "succeeded"} if action == "commit root outcome" { commit.Outcome = big } else { diff --git a/internal/session/runtime_test.go b/internal/session/runtime_test.go index 216d351c9..f6197b346 100644 --- a/internal/session/runtime_test.go +++ b/internal/session/runtime_test.go @@ -355,7 +355,7 @@ func TestRootTurnLifecycleIdentifiesExactTurn(t *testing.T) { if status == "interrupted" { _, err = store.InterruptRoot(t.Context(), rootID, "daemon stopped") } else { - commit := RootTurnCommit{RootID: rootID, AgentID: agentID, TurnID: turnID, Status: status, Model: "model", Provider: "provider"} + commit := RootTurnCommit{RootID: rootID, AgentID: agentID, TurnID: turnID, Status: status} switch status { case "failed": commit.Error = "provider unavailable" @@ -431,7 +431,6 @@ func TestRootTurnCommitAtomicallyAppendsHistoryAndConsumesAcknowledgedInbox(t *t RootID: rootID, AgentID: authority.AgentID, InboxSeq: first.InboxSeq, AcknowledgedInbox: []int64{steer.InboxSeq}, Messages: history, WorkspaceSeq: 5, WorkspaceRef: "snapshot-commit", - Model: "new-model", Provider: "new-provider", }); err != nil { t.Fatal(err) } @@ -440,8 +439,8 @@ func TestRootTurnCommitAtomicallyAppendsHistoryAndConsumesAcknowledgedInbox(t *t if err != nil { t.Fatal(err) } - if meta.Model != "new-model" || meta.Provider != "new-provider" { - t.Fatalf("route=%s/%s", meta.Provider, meta.Model) + if meta.Model != "old-model" || meta.Provider != "old-provider" { + t.Fatalf("turn commit changed the session route to %s/%s", meta.Provider, meta.Model) } if len(restored) != 7 || restored[0].Content != "stale" || restored[4].Content != "work" || restored[6].Content != "done" { t.Fatalf("restored history=%+v", restored) @@ -481,7 +480,6 @@ func TestInternalTurnInboxDoesNotPersistACommandOutcome(t *testing.T) { if err := st.CommitRootTurn(context.Background(), RootTurnCommit{ RootID: rootID, AgentID: authority.AgentID, InboxSeq: item.InboxSeq, Outcome: RuntimePayload{Data: bytes.Repeat([]byte("outcome"), 2048), MediaType: "text/plain", Source: "command outcome"}, - Model: "model", Provider: "provider", }); err != nil { t.Fatal(err) } @@ -524,7 +522,6 @@ func TestRootTurnCommitPreservesRawHistoryAcrossCompaction(t *testing.T) { if err := st.CommitRootTurn(context.Background(), RootTurnCommit{ RootID: rootID, AgentID: authority.AgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: "q4"}, {Role: "assistant", Content: "a4"}}, - Model: "model", Provider: "provider", }); err != nil { t.Fatal(err) } @@ -572,7 +569,6 @@ func TestRootTurnCommitMapsCompactionsWithoutPersistedSystem(t *testing.T) { RootID: rootID, AgentID: authority.AgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: input}, {Role: "assistant", Content: output}}, Compactions: []RootCompaction{{Summary: "summary " + input, Cutoff: cutoff, RawTailStart: rawTail}}, - Model: "model", Provider: "provider", }); err != nil { t.Fatal(err) } @@ -608,7 +604,7 @@ func TestRootTurnCommitRollsBackAsOneTransition(t *testing.T) { err = st.commitRootTurn(context.Background(), RootTurnCommit{ RootID: rootID, AgentID: authority.AgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: "work"}}, WorkspaceSeq: 1, WorkspaceRef: "rolled-back-snapshot", - GoalContinuation: "continue", Model: "model", Provider: "provider", + GoalContinuation: "continue", }, func() error { return want }) if !errors.Is(err, want) { t.Fatalf("commit error=%v", err) diff --git a/internal/session/span_test.go b/internal/session/span_test.go index f9d038777..18b2f21b4 100644 --- a/internal/session/span_test.go +++ b/internal/session/span_test.go @@ -133,7 +133,7 @@ func TestSpansRecordATurnItsCallsAndOutliveTheJournalWindow(t *testing.T) { } // The turn commit closes the turn span with the visible outcome. - if err := store.CommitRootTurn(context.Background(), RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Messages: []llm.Message{{Role: "assistant", Content: "All green."}}, Model: "model", Provider: "provider"}); err != nil { + if err := store.CommitRootTurn(context.Background(), RootTurnCommit{RootID: root, AgentID: agent, InboxSeq: seq, Messages: []llm.Message{{Role: "assistant", Content: "All green."}}}); err != nil { t.Fatal(err) } turn = spansByID(t, store, root, trace)[turnSpan] diff --git a/internal/session/title_admission_test.go b/internal/session/title_admission_test.go index 3478e1ec3..1dbeaf038 100644 --- a/internal/session/title_admission_test.go +++ b/internal/session/title_admission_test.go @@ -98,7 +98,7 @@ func TestTitleAttachmentOnlyWaitsAcrossTurnAndRestart(t *testing.T) { t.Fatal(err) } if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ - RootID: root, AgentID: root, InboxSeq: first.Command.IngressSeq, Model: "model", Provider: "provider", + RootID: root, AgentID: root, InboxSeq: first.Command.IngressSeq, Messages: []llm.Message{{Role: "user", Content: "expanded attachment text", Authored: true}, {Role: "assistant", Content: "done"}}, }); err != nil { t.Fatal(err) @@ -294,7 +294,7 @@ func TestTitleWaitsForQueuedTextAndSurvivesTurnFailure(t *testing.T) { t.Fatal(err) } if err := store.CommitRootTurn(t.Context(), RootTurnCommit{ - RootID: root, AgentID: agent, InboxSeq: first.Command.IngressSeq, Status: status, Model: "model", Provider: "provider", + RootID: root, AgentID: agent, InboxSeq: first.Command.IngressSeq, Status: status, Messages: []llm.Message{{Role: "user", Content: "expanded text", Authored: true}}, }); err != nil { t.Fatal(err) diff --git a/internal/session/title_test.go b/internal/session/title_test.go index 336fb6b37..38aee3793 100644 --- a/internal/session/title_test.go +++ b/internal/session/title_test.go @@ -85,7 +85,6 @@ func TestProvisionalTitlePersistsAcrossWritePaths(t *testing.T) { if err := store.CommitRootTurn(context.Background(), RootTurnCommit{ RootID: rootID, AgentID: authority.AgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: input, Authored: true}, {Role: "assistant", Content: "done"}}, - Model: "model", Provider: "provider", }); err != nil { t.Fatal(err) } diff --git a/internal/session/transcript_test.go b/internal/session/transcript_test.go index e0459a74b..00d04b6ad 100644 --- a/internal/session/transcript_test.go +++ b/internal/session/transcript_test.go @@ -23,7 +23,7 @@ func transcriptCommit(t *testing.T, store *Store, rootID, agentID string, turn i if err := store.StartRootTurn(t.Context(), rootID, agentID, item.InboxSeq); err != nil { t.Fatal(err) } - if err := store.CommitRootTurn(t.Context(), RootTurnCommit{RootID: rootID, AgentID: agentID, InboxSeq: item.InboxSeq, Messages: messages, Compactions: compactions, Model: "model", Provider: "provider"}); err != nil { + if err := store.CommitRootTurn(t.Context(), RootTurnCommit{RootID: rootID, AgentID: agentID, InboxSeq: item.InboxSeq, Messages: messages, Compactions: compactions}); err != nil { t.Fatal(err) } return @@ -318,7 +318,7 @@ func TestTranscriptRawCutoffUsesSequenceAndCompactionFailureIsAtomic(t *testing. t.Fatal(err) } cutoff := 3 - commit := RootTurnCommit{RootID: rootID, AgentID: rootAgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: "four"}}, Compactions: []RootCompaction{{Summary: "one and three", RawCutoff: &cutoff}}, Model: "model", Provider: "provider"} + commit := RootTurnCommit{RootID: rootID, AgentID: rootAgentID, InboxSeq: item.InboxSeq, Messages: []llm.Message{{Role: "user", Content: "four"}}, Compactions: []RootCompaction{{Summary: "one and three", RawCutoff: &cutoff}}} commitFailure := errors.New("injected after all transcript writes") if err := store.commitRootTurn(t.Context(), commit, func() error { return commitFailure }); !errors.Is(err, commitFailure) { t.Fatalf("injected failure = %v", err) From f62b5eec628b2d583793aa788dc2eb677941e0f8 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Sun, 27 Sep 2026 16:51:17 -0700 Subject: [PATCH 07/67] feat(effort): one vocabulary, concrete from creation (protocol 6.9) Effort had two vocabularies: explicit values (wire, sessions.effort, config, definitions) were off or a level with blank meaning not chosen, while applied values (runner, catalog helper, TUI state, HTTP field) used blank to mean off. Seven translators sat between them and the child spawn path had none, so session.effort.get and the web picker reported off for a reasoning session, and a child spawned with effort=off sent the literal to chat-completions. Standardize on off or a level everywhere. session.create accepts effort (protocol 6.9, additive) and the daemon stores a concrete value from creation: the request, else the definition default, else the configured default, resolved against the model's catalog entry by the new config.ResolveEffort. Rows saved blank before this are resolved once at open. Both llm encoders turn off into an omitted parameter. The catalog helper, compatibility rule, TUI and web app use the same values; the daemon label function, the TUI's translators and the Responses none special case are deleted. The web app sends effort on create instead of a create-then-session.effort two-step. Sessions no longer follow later changes to the global default; it is resolved when the session is created. Co-Authored-By: Claude Fable 5.1 --- cmd/whip/daemon.go | 20 +--- cmd/whip/daemon_test.go | 15 --- docs/features.md | 10 ++ docs/frontend.md | 7 +- docs/protocol-v2.md | 9 ++ internal/config/catalog.go | 12 +-- internal/config/catalog_test.go | 4 +- internal/config/effort.go | 31 ++++++ internal/config/effort_test.go | 33 ++++++ internal/daemon/client_control.go | 25 +---- internal/daemon/client_control_test.go | 2 +- internal/daemon/control.go | 55 +++++++--- internal/daemon/daemon.go | 13 +++ internal/daemon/definition_test.go | 4 +- internal/daemon/effort_vocabulary_test.go | 100 ++++++++++++++++++ internal/daemon/provider_service.go | 6 +- internal/daemon/skill_completion_test.go | 2 +- internal/llm/effort_boundary_test.go | 28 +++++ internal/llm/provider_compatibility.go | 5 + internal/llm/responses.go | 9 +- internal/protocol/runtime_contract.go | 15 +-- internal/protocol/types.go | 2 +- internal/session/command.go | 8 +- internal/session/definition_test.go | 4 +- internal/tui/client.go | 27 ++--- internal/tui/client_queue_test.go | 14 +-- internal/tui/effort.go | 64 ++--------- internal/tui/effort_test.go | 52 ++------- packages/app/src/model-selection.tsx | 4 +- packages/app/src/welcome.tsx | 8 +- packages/app/test/welcome.test.tsx | 9 +- packages/protocol/generated/index.d.ts | 1 + packages/protocol/generated/index.js | 2 +- .../protocol/generated/request-validators.js | 28 +++-- .../protocol/generated/response-validators.js | 26 +++-- .../protocol/schema/CreateSessionParams.json | 3 + packages/protocol/schema/manifest.json | 2 +- 37 files changed, 410 insertions(+), 249 deletions(-) create mode 100644 internal/config/effort.go create mode 100644 internal/config/effort_test.go create mode 100644 internal/daemon/effort_vocabulary_test.go create mode 100644 internal/llm/effort_boundary_test.go diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index dbecfa825..ea3857ba9 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -31,7 +31,6 @@ import ( "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" - "github.com/context-labs/whip/internal/tui" "github.com/context-labs/whip/internal/webgateway" ) @@ -141,11 +140,10 @@ func runDaemon(ctx context.Context, args []string) error { }) } ag.Vision = route.Vision - effort := meta.Effort - if effort == "" { - effort = definition.Model.Effort - } - ag.Effort = resolvedRuntimeEffort(providers.Catalogs(), route.Provider, route.Model, effort, runtimeCfg.DefaultEffort) + // The saved effort is concrete: the daemon resolves it at creation and + // upgrades older blank rows at open. "off" becomes an omitted parameter + // at the request boundary. + ag.Effort = meta.Effort ag.ResolveModel = func(model, provider string) (agent.ModelRoute, error) { currentCfg, loadErr := config.Load() if loadErr != nil { @@ -367,16 +365,6 @@ func daemonToolServices(cfg *config.Config, meta session.Meta, apiID string, cap return services } -func resolvedRuntimeEffort(catalogs map[string]config.Catalog, provider, modelID, stored, defaultEffort string) string { - if stored == "off" { - return "" - } - if stored != "" { - return stored - } - return tui.DefaultEffortFor(catalogs, provider, modelID, defaultEffort) -} - func rlmLimits(value config.RLMConfig) rlm.Limits { limits := rlm.DefaultLimits() if value.MaxConcurrentHostCalls != 0 { diff --git a/cmd/whip/daemon_test.go b/cmd/whip/daemon_test.go index fdc7baa49..85151dec2 100644 --- a/cmd/whip/daemon_test.go +++ b/cmd/whip/daemon_test.go @@ -165,21 +165,6 @@ func TestRunDaemonPublishesProtocolAndStopsCleanly(t *testing.T) { } } -func TestResolvedRuntimeEffortPreservesExplicitOffAndInheritance(t *testing.T) { - catalogs := map[string]config.Catalog{"provider": { - Models: []config.ModelInfoLite{{ID: "model", ReasoningEfforts: []string{"low", "high"}}}, - }} - if got := resolvedRuntimeEffort(catalogs, "provider", "model", "off", "high"); got != "" { - t.Fatalf("explicit off resolved to %q", got) - } - if got := resolvedRuntimeEffort(catalogs, "provider", "model", "", "high"); got != "high" { - t.Fatalf("inherited effort resolved to %q", got) - } - if got := resolvedRuntimeEffort(catalogs, "provider", "model", "low", "high"); got != "low" { - t.Fatalf("session override resolved to %q", got) - } -} - func TestRunDaemonRejectsInvalidArguments(t *testing.T) { if err := daemonCLI([]string{"unexpected"}); err == nil { t.Fatal("hidden daemon accepted positional arguments") diff --git a/docs/features.md b/docs/features.md index b8b6db2ea..79f92bfc3 100644 --- a/docs/features.md +++ b/docs/features.md @@ -304,6 +304,16 @@ root prompt (`evals/rlm`). [agent-loop.md](agent-loop.md). - Model-to-provider routing, live catalog discovery, context/output limits, reasoning effort, vision flags, sampling parameters, and pricing. +- Reasoning effort is one vocabulary, `off` or a catalog level, in the saved + session row, the runner, the TUI, the web app and the wire. A session stores + a concrete effort from creation: the `session.create.effort` request, else + the agent definition's default, else the configured default, resolved against + the model's catalog entry (`config.ResolveEffort`). Sessions saved before + this rule are resolved the first time the daemon opens them. `off` becomes an + omitted request parameter at the llm encoders. Switching to a model that does + not support the saved level sets the session to `off`. Coverage: + `TestSessionCreationStoresConcreteEffort`, `TestOpenResolvesLegacyBlankEffort`, + `TestOffEffortOmitsReasoningParameter`, `TestResolveEffortModelAware`. - `models.call` and `models.batch` provide stateless analysis without creating durable child identities; batch results retain input order. - Prompt-cache keys are stable per retained session: the daemon stamps diff --git a/docs/frontend.md b/docs/frontend.md index 3135f1ce9..cf8209fdb 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1498,9 +1498,10 @@ Provider rows grow for wrapped labels and mobile touch targets. Connection and model confirmation reuse the existing flows; completing setup returns focus to the preserved draft composer without sending it. -Sending the first message is three commands through the runtime's command -runner: `sessions.create`, an optional `session.effort` with `persist_default: -false` when the draft chose an effort, then `submit`. Acceptance of the submit +Sending the first message is two commands through the runtime's command +runner: `sessions.create`, carrying `effort` when the draft chose one (the +daemon otherwise resolves the configured default against the model, protocol +6.9), then `submit`. Acceptance of the submit promotes the New Chat tab in place into the session's tab (`SessionTabs.promoteNew`); the router follows only when that draft route is still focused, so a background pane never steals focus. The draft is cleared only if its text is still what was diff --git a/docs/protocol-v2.md b/docs/protocol-v2.md index e3a5a004a..5dfb5e2c4 100644 --- a/docs/protocol-v2.md +++ b/docs/protocol-v2.md @@ -17,6 +17,15 @@ files. Standalone validators require no runtime code generation or Ajv dependenc Typed RPC/runtime maps classify query, durable and ephemeral operations. The handwritten `@whip/sdk` consumes this contract; see [SDK usage](../packages/sdk/README.md). +Protocol **6.9** adds `session.create.effort` and makes effort one vocabulary. +An effort value is `off` or a catalog level everywhere; blank is not a value. +A session stores a concrete effort from creation: the request, else the agent +definition's default, else the configured default, resolved against the model's +catalog entry. `session.effort.get` returns that saved value, which is also the +value the runner applies. Sessions created before 6.9 are resolved the same way +the first time the daemon opens them. Additive; 6.8 clients keep creating +sessions with the resolved default. + Protocol **6.8** adds optional versioned transcript `presentation` metadata, stream `part_id`, and allowlisted operation `display` fields. Durable presentation stays in existing raw JSON records, separate from opaque provider continuation. diff --git a/internal/config/catalog.go b/internal/config/catalog.go index 8ff3bf445..24f77baa0 100644 --- a/internal/config/catalog.go +++ b/internal/config/catalog.go @@ -112,18 +112,18 @@ func (c Catalog) Find(id string) *ModelInfoLite { } // Efforts returns the reasoning-effort levels available for a model id, in -// provider order and prefixed by "" (off): ["", "low", "medium", "high", …]. -// "" is the only entry (i.e. the model doesn't reason) when the catalog has no +// provider order and prefixed by "off": ["off", "low", "medium", "high", …]. +// "off" is the only entry (i.e. the model doesn't reason) when the catalog has no // entry for the model or the entry advertises no efforts. A "none" effort is -// collapsed into the leading off (""). +// collapsed into the leading "off". func (c Catalog) Efforts(id string) []string { mi := c.Find(id) if mi == nil || len(mi.ReasoningEfforts) == 0 { - return []string{""} + return []string{"off"} } - out := []string{""} + out := []string{"off"} for _, e := range mi.ReasoningEfforts { - if e != "none" { // "none" is our off ("") + if e != "none" && e != "off" { // upstream "none" is our "off" out = append(out, e) } } diff --git a/internal/config/catalog_test.go b/internal/config/catalog_test.go index 2630d101e..817b8761e 100644 --- a/internal/config/catalog_test.go +++ b/internal/config/catalog_test.go @@ -48,11 +48,11 @@ func TestCatalogEffortsNormalizesOffAndMissingModels(t *testing.T) { {ID: "reasoning", ReasoningEfforts: []string{"none", "low", "high"}}, {ID: "plain"}, }} - if got := catalog.Efforts("reasoning"); !slices.Equal(got, []string{"", "low", "high"}) { + if got := catalog.Efforts("reasoning"); !slices.Equal(got, []string{"off", "low", "high"}) { t.Fatalf("reasoning efforts = %v", got) } for _, model := range []string{"plain", "missing"} { - if got := catalog.Efforts(model); !slices.Equal(got, []string{""}) { + if got := catalog.Efforts(model); !slices.Equal(got, []string{"off"}) { t.Errorf("%s efforts = %v", model, got) } } diff --git a/internal/config/effort.go b/internal/config/effort.go new file mode 100644 index 000000000..3431284de --- /dev/null +++ b/internal/config/effort.go @@ -0,0 +1,31 @@ +package config + +import "slices" + +// ResolveEffort turns the effort a session was asked for into the concrete +// value it stores: pinned when set (an explicit config or definition choice is +// honored as-is, even if the model later turns out not to support it), else +// "low" when the model advertises it, else the lowest advertised level, else +// "off" when the catalog confirms the model does not reason, else "low" as a +// best guess for a model the catalog does not know. The result is always +// "off" or a level; blank is never an effort value. +func ResolveEffort(catalogs map[string]Catalog, provider, modelID, pinned string) string { + if pinned != "" { + return pinned + } + if c, ok := catalogs[provider]; ok { + if mi := c.Find(modelID); mi != nil { + levels := c.Efforts(modelID) // ["off"] for a non-reasoning model + if slices.Contains(levels, "low") { + return "low" + } + for _, e := range levels { + if e != "off" { + return e + } + } + return "off" + } + } + return "low" +} diff --git a/internal/config/effort_test.go b/internal/config/effort_test.go new file mode 100644 index 000000000..0a5863ef0 --- /dev/null +++ b/internal/config/effort_test.go @@ -0,0 +1,33 @@ +package config + +import "testing" + +// ResolveEffort picks "low" when the model advertises it, the lowest supported +// level otherwise, and "off" for non-reasoning models, so a session never +// opens on an effort the provider would reject. An explicit pinned value is +// honored verbatim, even if unsupported. Blank is never returned. +func TestResolveEffortModelAware(t *testing.T) { + cats := map[string]Catalog{ + "inference": {Models: []ModelInfoLite{ + {ID: "deepseek-v4-flash", ReasoningEfforts: []string{"low", "high", "max"}}, // no medium + {ID: "claude-opus-5", ReasoningEfforts: []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"}}, + {ID: "gemini-3.5-flash"}, // no reasoning_efforts + }}, + } + cases := []struct{ model, pinned, want string }{ + {"deepseek-v4-flash", "", "low"}, // low is supported → low + {"claude-opus-5", "", "low"}, // low is supported → low + {"gemini-3.5-flash", "", "off"}, // non-reasoning → off + {"deepseek-v4-flash", "high", "high"}, // pinned honored + {"deepseek-v4-flash", "medium", "medium"}, // pinned honored even though unsupported + {"gemini-3.5-flash", "off", "off"}, // explicit off stays off + } + for _, c := range cases { + if got := ResolveEffort(cats, "inference", c.model, c.pinned); got != c.want { + t.Fatalf("ResolveEffort(%q, pinned=%q): got %q want %q", c.model, c.pinned, got, c.want) + } + } + if got := ResolveEffort(map[string]Catalog{}, "elsewhere", "anything", ""); got != "low" { + t.Fatalf("unknown provider should fall back to low, got %q", got) + } +} diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index eb340da33..2ed5b81b9 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -1046,7 +1046,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw s.emitSessionUpdate(ctx, "session.cwd.updated", SessionUpdateEvent{WorkingDir: path}) return path, nil case "session.effort.get": - return daemonEffortLabel(s.effort), nil + return s.effort, nil case "session.effort": requested := strings.TrimSpace(payload.Effort) if requested == "" { @@ -1063,12 +1063,8 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw if err := s.store.SetEffort(s.id, requested); err != nil { return "", err } - level := requested - if level == "off" { - level = "" - } if setter, ok := s.runner.(interface{ SetEffort(string) }); ok { - setter.SetEffort(level) + setter.SetEffort(requested) } s.effort = requested if payload.PersistDefault { @@ -1078,7 +1074,7 @@ func (s *Session) applyClientCommand(ctx context.Context, operation string, raw } s.emitSessionUpdate(ctx, "session.effort.updated", SessionUpdateEvent{Effort: requested, EffortChanged: true}) - return daemonEffortLabel(requested), nil + return requested, nil case "session.model.get": return marshalClientOutput(protocol.ModelResult{Model: s.model, Provider: s.provider}, nil) @@ -1567,13 +1563,6 @@ func (s *Session) installReplacement(ctx context.Context, replacement *clientRep return model + " @ " + provider, nil } -func daemonEffortLabel(level string) string { - if level == "" { - return "off" - } - return level -} - func validateEffort(model, provider, requested string) error { cfg, err := config.Load() if err != nil { @@ -1583,7 +1572,7 @@ func validateEffort(model, provider, requested string) error { } func validateConfiguredEffort(cfg *config.Config, model, provider, requested string) error { - if requested == "off" || requested == "" { + if requested == "off" { return nil } known := slices.Contains([]string{"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"}, requested) @@ -1608,10 +1597,6 @@ func validateConfiguredEffort(cfg *config.Config, model, provider, requested str } func compatibleEffort(model, provider, current string) string { - runtimeLevel := current - if runtimeLevel == "off" { - runtimeLevel = "" - } cfg, err := config.Load() if err != nil { return current @@ -1625,7 +1610,7 @@ func compatibleEffort(model, provider, current string) string { return current } info := catalog.Find(apiID) - if info == nil || slices.Contains(append([]string{""}, info.ReasoningEfforts...), runtimeLevel) { + if info == nil || slices.Contains(append([]string{"off"}, info.ReasoningEfforts...), current) { return current } return "off" diff --git a/internal/daemon/client_control_test.go b/internal/daemon/client_control_test.go index 145d47b62..fe83a5913 100644 --- a/internal/daemon/client_control_test.go +++ b/internal/daemon/client_control_test.go @@ -1114,7 +1114,7 @@ func TestEffortControlPreservesExplicitOffAndGlobalDefaultOnCompatibilityChange( result := clientCommand(t, root, "tui", "effort-off", "session.effort", map[string]any{"effort": "off", "persist_default": true}) meta, _, loadErr := store.Load(rootID) cfg, configErr := config.Load() - if result.Status != "succeeded" || runner.effort != "" || loadErr != nil || configErr != nil || meta.Effort != "off" || cfg.DefaultEffort != "off" { + if result.Status != "succeeded" || runner.effort != "off" || loadErr != nil || configErr != nil || meta.Effort != "off" || cfg.DefaultEffort != "off" { t.Fatalf("off result=%+v runner=%q meta=%q default=%q load=%v config=%v", result, runner.effort, meta.Effort, cfg.DefaultEffort, loadErr, configErr) } }) diff --git a/internal/daemon/control.go b/internal/daemon/control.go index 00fd1345e..27ef1598f 100644 --- a/internal/daemon/control.go +++ b/internal/daemon/control.go @@ -85,7 +85,10 @@ type CreateSession struct { CWD string `json:"cwd"` Model string `json:"model"` Provider string `json:"provider"` - PermissionMode string `json:"permission_mode,omitempty"` + // Effort is "off" or a catalog level. Blank asks the daemon to resolve the + // definition's default, else the configured default, against the model. + Effort string `json:"effort,omitempty"` + PermissionMode string `json:"permission_mode,omitempty"` } func (c *Control) CreateSession(ctx context.Context, admission session.CommandAdmission, create CreateSession) (record session.CommandRecord, err error) { @@ -104,7 +107,7 @@ func (c *Control) CreateSession(ctx context.Context, admission session.CommandAd } create, err = resolveSessionDefaults(actorCtx, c.store, create) if err == nil { - record, err = c.store.CreateSessionForCommandWithDefinition(actorCtx, admission.ClientID, admission.CommandID, create.Kind, create.CWD, create.Model, create.Provider, create.PermissionMode, create.ExecutionEngine, create.Definition, create.DefinitionRevision) + record, err = c.store.CreateSessionForCommandWithDefinition(actorCtx, admission.ClientID, admission.CommandID, create.Kind, create.CWD, create.Model, create.Provider, create.Effort, create.PermissionMode, create.ExecutionEngine, create.Definition, create.DefinitionRevision) } if err != nil { _, finishErr := c.store.FinishCommand(actorCtx, admission.ClientID, admission.CommandID, "failed", session.RuntimePayload{Data: encodeCommandOutcome("session.create", "", err), MediaType: "application/json"}) @@ -415,7 +418,8 @@ func sessionDefaults(create CreateSession, definition agentdef.Definition) (Crea } needRoute := create.Kind == session.SessionKindAgent && (create.Model == "" || create.Provider == "") needPermissionMode := create.Kind == session.SessionKindAgent && create.PermissionMode == "" - if !needRoute && !needPermissionMode && create.ExecutionEngine != "" { + needEffort := create.Kind == session.SessionKindAgent + if !needRoute && !needPermissionMode && !needEffort && create.ExecutionEngine != "" { return create, nil } cfg, _, err := config.ReadVersioned() @@ -431,16 +435,43 @@ func sessionDefaults(create CreateSession, definition agentdef.Definition) (Crea if create.ExecutionEngine != "starlark" && create.ExecutionEngine != "quickjs" { return create, fmt.Errorf("unknown default execution engine %q", create.ExecutionEngine) } - if !needRoute { - return create, nil - } - provider, _, _, _, err := cfg.ResolveRoute(create.Model, create.Provider) - if err != nil { - return create, err + if needRoute { + provider, _, _, _, err := cfg.ResolveRoute(create.Model, create.Provider) + if err != nil { + return create, err + } + if create.Model == "" { + create.Model = cfg.DefaultModel + } + create.Provider = provider } - if create.Model == "" { - create.Model = cfg.DefaultModel + if needEffort { + if create.Effort != "" { + if err := validateConfiguredEffort(cfg, create.Model, create.Provider, create.Effort); err != nil { + return create, err + } + } + create.Effort = resolveEffort(cfg, create.Model, create.Provider, create.Effort, definition.Model.Effort) } - create.Provider = provider return create, nil } + +// resolveEffort turns a requested or inherited effort into the concrete value +// a session stores: the explicit request, else the definition's default, else +// the configured default, resolved against the model's catalog entry so a new +// session never opens on a level its provider rejects. The result is "off" or +// a level; blank is never stored. +func resolveEffort(cfg *config.Config, model, provider, requested, definitionDefault string) string { + pinned := requested + if pinned == "" { + pinned = definitionDefault + } + if pinned == "" { + pinned = cfg.DefaultEffort + } + catalogProvider, modelID := provider, model + if resolved, _, _, apiID, err := cfg.ResolveRoute(model, provider); err == nil { + catalogProvider, modelID = resolved, apiID + } + return config.ResolveEffort(config.LoadCatalogs(), catalogProvider, modelID, pinned) +} diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 28c509b0d..a020b92e5 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/terminal" @@ -251,6 +252,18 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err if err != nil { return nil, err } + if meta.Kind == session.SessionKindAgent && meta.Effort == "" { + // Rows saved before efforts were resolved at creation follow the same + // rule once, so the runner and every reader share one concrete value. + cfg, err := config.Load() + if err != nil { + cfg = config.Default() + } + meta.Effort = resolveEffort(cfg, meta.Model, meta.Provider, "", definition.Model.Effort) + if err := d.store.SetEffort(meta.ID, meta.Effort); err != nil { + return nil, err + } + } authority, err := d.store.EnsureRootAuthority(d.ctx, meta.ID, rootGrants(definition, hasDefinition)) if err != nil { return nil, err diff --git a/internal/daemon/definition_test.go b/internal/daemon/definition_test.go index 18dd25c71..463ab14d8 100644 --- a/internal/daemon/definition_test.go +++ b/internal/daemon/definition_test.go @@ -168,7 +168,7 @@ func createDefinitionRoot(t *testing.T, store *session.Store, definition string) if _, err := store.AdmitCommand(t.Context(), session.CommandAdmission{ClientID: "definitions", CommandID: id, Scope: session.CommandScopeDaemon, RequestDigest: id}); err != nil { t.Fatal(err) } - record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, session.SessionKindAgent, t.TempDir(), "model", "provider", "", "", create.Definition, create.DefinitionRevision) + record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, session.SessionKindAgent, t.TempDir(), "model", "provider", "", "", "", create.Definition, create.DefinitionRevision) if err != nil { t.Fatal(err) } @@ -277,7 +277,7 @@ func TestRegisteredDefinitionRunsAndResolves(t *testing.T) { if _, err := store.AdmitCommand(t.Context(), session.CommandAdmission{ClientID: "definitions", CommandID: id, Scope: session.CommandScopeDaemon, RequestDigest: id}); err != nil { t.Fatal(err) } - record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, session.SessionKindAgent, t.TempDir(), "model", "provider", "", "", create.Definition, create.DefinitionRevision) + record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, session.SessionKindAgent, t.TempDir(), "model", "provider", "", "", "", create.Definition, create.DefinitionRevision) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/effort_vocabulary_test.go b/internal/daemon/effort_vocabulary_test.go new file mode 100644 index 000000000..2e1da9a93 --- /dev/null +++ b/internal/daemon/effort_vocabulary_test.go @@ -0,0 +1,100 @@ +package daemon + +import ( + "context" + "encoding/json" + "fmt" + "path/filepath" + "testing" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +// Effort is one vocabulary, "off" or a level, and every session stores a +// concrete value from creation: the request, else the definition's default, +// else the configured default, resolved against the model's catalog entry. +func TestSessionCreationStoresConcreteEffort(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + defer func() { _ = value.Close() }() + create := func(t *testing.T, commandID, effort string) (string, error) { + t.Helper() + admission := session.CommandAdmission{ + ClientID: "client", CommandID: commandID, RequestDigest: "digest-" + commandID, + Payload: session.RuntimePayload{Data: []byte(`{}`)}, + } + record, err := value.control.CreateSession(t.Context(), admission, CreateSession{ + Kind: session.SessionKindAgent, CWD: t.TempDir(), Model: "m", Provider: "p", Effort: effort, + }) + if err != nil { + return "", err + } + if record.Status != "succeeded" { + return "", fmt.Errorf("create %s: %+v", commandID, record) + } + var result protocol.RootIDResult + if err := json.Unmarshal(record.Outcome.Inline, &result); err != nil { + return "", err + } + return result.RootID, nil + } + for _, test := range []struct{ name, requested, want string }{ + {"resolved default", "", "low"}, + {"explicit off", "off", "off"}, + {"explicit level", "high", "high"}, + } { + t.Run(test.name, func(t *testing.T) { + rootID, err := create(t, "create-"+test.requested, test.requested) + if err != nil { + t.Fatal(err) + } + meta, err := store.LoadMeta(rootID) + if err != nil || meta.Effort != test.want { + t.Fatalf("saved effort = %q, want %q (%v)", meta.Effort, test.want, err) + } + }) + } + if _, err := create(t, "create-bogus", "bogus"); err == nil { + t.Fatal("unknown effort level accepted at creation") + } +} + +// Rows saved before efforts were resolved at creation are resolved the same +// way the first time the daemon opens them, so the runner and every reader +// share one concrete value. +func TestOpenResolvesLegacyBlankEffort(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) // store.Create leaves effort blank + if meta, err := store.LoadMeta(rootID); err != nil || meta.Effort != "" { + t.Fatalf("fixture effort = %q %v", meta.Effort, err) + } + constructed := "" + value, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + constructed = meta.Effort + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + defer func() { _ = value.Close() }() + root, err := value.Open(rootID) + if err != nil { + t.Fatal(err) + } + meta, err := store.LoadMeta(rootID) + if err != nil || meta.Effort != "low" || constructed != "low" { + t.Fatalf("legacy effort saved=%q constructed=%q %v", meta.Effort, constructed, err) + } + if get := clientCommand(t, root, "tui", "effort-get", "session.effort.get", map[string]any{}); get.Output != "low" { + t.Fatalf("effort.get = %+v", get) + } +} diff --git a/internal/daemon/provider_service.go b/internal/daemon/provider_service.go index fdf16201e..25f1adc00 100644 --- a/internal/daemon/provider_service.go +++ b/internal/daemon/provider_service.go @@ -283,7 +283,9 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon if p.MaxRetries != nil { c.MaxRetries = *p.MaxRetries } - if p.DefaultEffort != nil { + // A blank configured default is "not chosen": each new session resolves + // its own concrete effort against the model at creation. + if p.DefaultEffort != nil && *p.DefaultEffort != "" { if err := validateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, *p.DefaultEffort); err != nil { return err } @@ -293,7 +295,7 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon if !selection.Ready { return errors.New("select a model available on a connected provider before saving defaults") } - if p.DefaultEffort == nil && validateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, c.DefaultEffort) != nil { + if p.DefaultEffort == nil && c.DefaultEffort != "" && validateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, c.DefaultEffort) != nil { c.DefaultEffort = "" } } diff --git a/internal/daemon/skill_completion_test.go b/internal/daemon/skill_completion_test.go index 6230c8dd5..3610f7079 100644 --- a/internal/daemon/skill_completion_test.go +++ b/internal/daemon/skill_completion_test.go @@ -262,7 +262,7 @@ func TestWorkspaceSkillsCompletePinnedNamedChildDefinition(t *testing.T) { if _, err := store.AdmitCommand(t.Context(), session.CommandAdmission{ClientID: "test", CommandID: "create", Scope: session.CommandScopeDaemon, RequestDigest: "create"}); err != nil { t.Fatal(err) } - record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "test", "create", session.SessionKindAgent, cwd, "model", "provider", "prompt", "starlark", definition.ID, "v1") + record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "test", "create", session.SessionKindAgent, cwd, "model", "provider", "", "prompt", "starlark", definition.ID, "v1") if err != nil { t.Fatal(err) } diff --git a/internal/llm/effort_boundary_test.go b/internal/llm/effort_boundary_test.go new file mode 100644 index 000000000..97f231e3c --- /dev/null +++ b/internal/llm/effort_boundary_test.go @@ -0,0 +1,28 @@ +package llm + +import ( + "strings" + "testing" +) + +// "off" is the explicit no-reasoning level everywhere in whip. Both request +// encoders translate it into an omitted parameter; a level passes through. +func TestOffEffortOmitsReasoningParameter(t *testing.T) { + client := New("https://example.test/v1", "key") + chat, err := client.encodeChatRequest(Request{Model: "m", ReasoningEffort: "off"}) + if err != nil || strings.Contains(string(chat), "reasoning_effort") { + t.Fatalf("chat off = %s %v", chat, err) + } + chat, err = client.encodeChatRequest(Request{Model: "m", ReasoningEffort: "high"}) + if err != nil || !strings.Contains(string(chat), `"reasoning_effort":"high"`) { + t.Fatalf("chat high = %s %v", chat, err) + } + responses, err := encodeResponses(Request{Model: "m", ReasoningEffort: "off"}, "") + if err != nil || strings.Contains(string(responses), `"reasoning"`) { + t.Fatalf("responses off = %s %v", responses, err) + } + responses, err = encodeResponses(Request{Model: "m", ReasoningEffort: "high"}, "") + if err != nil || !strings.Contains(string(responses), `"effort":"high"`) { + t.Fatalf("responses high = %s %v", responses, err) + } +} diff --git a/internal/llm/provider_compatibility.go b/internal/llm/provider_compatibility.go index d2d7cb879..d9acdcd90 100644 --- a/internal/llm/provider_compatibility.go +++ b/internal/llm/provider_compatibility.go @@ -8,6 +8,11 @@ import ( // encodeChatRequest limits provider-specific changes to exact preset roots. // A custom proxy keeps the generic wire contract, even with a familiar hostname. func (c *Client) encodeChatRequest(req Request) ([]byte, error) { + // "off" is the explicit no-reasoning level everywhere else in whip; the + // wire contract expresses it by omitting the parameter. + if req.ReasoningEffort == "off" { + req.ReasoningEffort = "" + } switch c.BaseURL { case "https://api.cerebras.ai/v1", "https://api.groq.com/openai/v1", "https://api.deepseek.com", "https://api.fireworks.ai/inference/v1", "https://api.together.ai/v1", "https://api.deepinfra.com/v1/openai": diff --git a/internal/llm/responses.go b/internal/llm/responses.go index f3b9ac8ab..cc44b74b0 100644 --- a/internal/llm/responses.go +++ b/internal/llm/responses.go @@ -126,12 +126,9 @@ func encodeResponsesWithLimit(req Request, accountID string, maxOutput int) ([]b if maxOutput > 0 { body["max_output_tokens"] = maxOutput } - if req.ReasoningEffort != "" { - effort := req.ReasoningEffort - if effort == "off" { - effort = "none" - } - body["reasoning"] = map[string]string{"effort": effort, "summary": "auto"} + // "off" omits the reasoning object, matching the chat-completions encoder. + if req.ReasoningEffort != "" && req.ReasoningEffort != "off" { + body["reasoning"] = map[string]string{"effort": req.ReasoningEffort, "summary": "auto"} } if req.PromptCacheKey != "" { body["prompt_cache_key"] = normalizeCacheKey(req.PromptCacheKey) diff --git a/internal/protocol/runtime_contract.go b/internal/protocol/runtime_contract.go index d2d32c6b8..47aaf9c42 100644 --- a/internal/protocol/runtime_contract.go +++ b/internal/protocol/runtime_contract.go @@ -11,12 +11,15 @@ import ( type CreateSessionParams struct { ExecutionEngine string `json:"execution_engine,omitempty"` // Definition selects the agent definition; empty means the coding agent. - Definition string `json:"definition,omitempty"` - Kind session.SessionKind `json:"kind"` - CWD string `json:"cwd"` - Model string `json:"model"` - Provider string `json:"provider"` - PermissionMode string `json:"permission_mode,omitempty"` + Definition string `json:"definition,omitempty"` + Kind session.SessionKind `json:"kind"` + CWD string `json:"cwd"` + Model string `json:"model"` + Provider string `json:"provider"` + // Effort is "off" or a catalog level; blank resolves the definition's + // default, else the configured default, against the model. Protocol 6.9. + Effort string `json:"effort,omitempty"` + PermissionMode string `json:"permission_mode,omitempty"` } type RootParams struct { RootID string `json:"root_id"` diff --git a/internal/protocol/types.go b/internal/protocol/types.go index cd517f973..2b988a9e3 100644 --- a/internal/protocol/types.go +++ b/internal/protocol/types.go @@ -12,7 +12,7 @@ import ( const ( Major = 6 - Minor = 8 + Minor = 9 SessionTitleNotificationsCapability = "session_title_notifications" ) diff --git a/internal/session/command.go b/internal/session/command.go index 62b8f8a65..06bf67060 100644 --- a/internal/session/command.go +++ b/internal/session/command.go @@ -212,14 +212,14 @@ func (s *Store) CreateSessionForCommandWithPermission(ctx context.Context, clien // CreateSessionForCommandWithEngine pins language with creation and its command // receipt. The session runs the coding agent. func (s *Store) CreateSessionForCommandWithEngine(ctx context.Context, clientID, commandID string, kind SessionKind, cwd, model, provider, permissionMode, engine string) (CommandRecord, error) { - return s.CreateSessionForCommandWithDefinition(ctx, clientID, commandID, kind, cwd, model, provider, permissionMode, engine, "coding", "") + return s.CreateSessionForCommandWithDefinition(ctx, clientID, commandID, kind, cwd, model, provider, "", permissionMode, engine, "coding", "") } // CreateSessionForCommandWithDefinition records which agent definition the // session executes and, for a registered definition, the revision it pins. The // daemon validates both against its registry; the store only requires that an // agent session names a definition. -func (s *Store) CreateSessionForCommandWithDefinition(ctx context.Context, clientID, commandID string, kind SessionKind, cwd, model, provider, permissionMode, engine, definition, revision string) (CommandRecord, error) { +func (s *Store) CreateSessionForCommandWithDefinition(ctx context.Context, clientID, commandID string, kind SessionKind, cwd, model, provider, effort, permissionMode, engine, definition, revision string) (CommandRecord, error) { if engine == "" { engine = "starlark" } @@ -259,8 +259,8 @@ func (s *Store) CreateSessionForCommandWithDefinition(ctx context.Context, clien return CommandRecord{}, err } stamp := now() - if _, err := tx.ExecContext(ctx, `INSERT INTO sessions(id,kind,created_at,updated_at,cwd,model,provider,permission_mode,execution_engine,definition,definition_revision) VALUES(?,?,?,?,?,?,?,?,?,?,?)`, - rootID, kind, stamp, stamp, cwd, model, provider, permissionMode, engine, definition, revision); err != nil { + if _, err := tx.ExecContext(ctx, `INSERT INTO sessions(id,kind,created_at,updated_at,cwd,model,provider,effort,permission_mode,execution_engine,definition,definition_revision) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)`, + rootID, kind, stamp, stamp, cwd, model, provider, effort, permissionMode, engine, definition, revision); err != nil { return CommandRecord{}, err } outcome, _ := json.Marshal(struct { diff --git a/internal/session/definition_test.go b/internal/session/definition_test.go index f4c4cc1b9..f84d223bf 100644 --- a/internal/session/definition_test.go +++ b/internal/session/definition_test.go @@ -75,7 +75,7 @@ func createDefinitionSession(t *testing.T, store *Store, definition string) (str if _, err := store.AdmitCommand(t.Context(), CommandAdmission{ClientID: "definitions", CommandID: id, Scope: CommandScopeDaemon, RequestDigest: id}); err != nil { t.Fatal(err) } - record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, SessionKindAgent, t.TempDir(), "model", "provider", "", "", definition, "") + record, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, SessionKindAgent, t.TempDir(), "model", "provider", "", "", "", definition, "") if err != nil { return "", err } @@ -217,7 +217,7 @@ func TestRegisteredDefinitionsAreIdempotentAndPinned(t *testing.T) { if _, err := store.AdmitCommand(t.Context(), CommandAdmission{ClientID: "definitions", CommandID: id, Scope: CommandScopeDaemon, RequestDigest: id}); err != nil { t.Fatal(err) } - created2, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, SessionKindAgent, t.TempDir(), "model", "provider", "", "", "support-bot", "rev-a") + created2, err := store.CreateSessionForCommandWithDefinition(t.Context(), "definitions", id, SessionKindAgent, t.TempDir(), "model", "provider", "", "", "", "support-bot", "rev-a") if err != nil { t.Fatal(err) } diff --git a/internal/tui/client.go b/internal/tui/client.go index 876c3ac33..84451edb4 100644 --- a/internal/tui/client.go +++ b/internal/tui/client.go @@ -139,7 +139,7 @@ func Run(cfg *config.Config, modelName, provName, resumeID string, cautious, yol cfg: cfg, client: client, clientState: ClientDisconnected, clientView: clientPresentation{ modelID: apiID, contextLimit: contextLimit, - effort: DefaultEffortFor(catalogs, provName, apiID, cfg.DefaultEffort), + effort: config.ResolveEffort(catalogs, provName, apiID, cfg.DefaultEffort), messages: []llm.Message{{Role: "system"}}, }, modelName: modelName, provName: provName, @@ -360,19 +360,10 @@ func (m *model) applyClientRoute(modelName, providerName string) { } } +// applyStoredEffort shows the session's saved effort. The daemon resolves a +// concrete value at creation, so the saved value is the applied one. func (m *model) applyStoredEffort(stored string) { - switch stored { - case "off": - m.clientView.effort = "" - case "": - if m.cfg == nil { - m.clientView.effort = "" - return - } - m.clientView.effort = DefaultEffortFor(m.catalogs, m.provName, m.displayModelID(), m.cfg.DefaultEffort) - default: - m.clientView.effort = stored - } + m.clientView.effort = stored } func (m *model) rebuildClientTranscript() { @@ -1604,7 +1595,7 @@ func (m *model) openThinPalette() { commandItem("Model", "Agent", "/model", true), { title: "Reasoning effort", category: "Agent", - dynDesc: func(value *model) string { return "current: " + effortLabel(value.displayEffort()) }, + dynDesc: func(value *model) string { return "current: " + value.displayEffort() }, dynHint: func(*model) string { return "/effort" }, run: func(value *model) (bubbletea.Model, bubbletea.Cmd) { value.openThinEffortPalette() @@ -1829,7 +1820,7 @@ func (m *model) openThinEffortPalette() { items := make([]paletteItem, 0, len(m.effortsFor())) for _, level := range m.effortsFor() { items = append(items, paletteItem{ - title: "Effort: " + effortLabel(level), category: "Agent", + title: "Effort: " + level, category: "Agent", dynDesc: func(value *model) string { if value.displayEffort() == level { return "current" @@ -1838,7 +1829,7 @@ func (m *model) openThinEffortPalette() { }, run: func(value *model) (bubbletea.Model, bubbletea.Cmd) { value.palette = nil - return value.submitClientAction("session.effort", protocol.EffortParams{Effort: effortLabel(level), PersistDefault: true}, "") + return value.submitClientAction("session.effort", protocol.EffortParams{Effort: level, PersistDefault: true}, "") }, }) } @@ -1936,12 +1927,12 @@ func (m *model) thinCommand(text string) (bubbletea.Model, bubbletea.Cmd) { levels := m.effortsFor() names := make([]string, len(levels)) for index := range levels { - names[index] = effortLabel(levels[index]) + names[index] = levels[index] } m.append(errStyle.Render("unknown effort level; " + m.modelName + " supports: " + strings.Join(names, ", "))) return m, nil } - return m.submitClientAction("session.effort", protocol.EffortParams{Effort: effortLabel(level), PersistDefault: true}, "") + return m.submitClientAction("session.effort", protocol.EffortParams{Effort: level, PersistDefault: true}, "") case "model", "model-for-session": if m.beforeSession() { return m, m.openProviderSetup() diff --git a/internal/tui/client_queue_test.go b/internal/tui/client_queue_test.go index be3d0ab83..d5ebe093e 100644 --- a/internal/tui/client_queue_test.go +++ b/internal/tui/client_queue_test.go @@ -320,28 +320,30 @@ func TestSessionMetadataEventsUpdateHeaderRouteAndContext(t *testing.T) { t.Fatal("session metadata event was not handled") } if m.sessTitle != "renamed" || m.modelName != "next-model" || m.provName != "next-provider" || - m.displayModelID() != "api-next" || m.displayEffort() != "" || m.displayContextLimit() != 256 || + m.displayModelID() != "api-next" || m.displayEffort() != "off" || m.displayContextLimit() != 256 || m.clientView.workingDir != "/tmp/project" { t.Fatalf("metadata was not reduced: title=%q route=%s@%s id=%q effort=%q context=%d cwd=%q", m.sessTitle, m.modelName, m.provName, m.displayModelID(), m.displayEffort(), m.displayContextLimit(), m.clientView.workingDir) } } -func TestSnapshotDistinguishesInheritedEffortFromExplicitOff(t *testing.T) { +// The daemon stores a concrete effort ("off" or a level) from creation, so the +// TUI shows the saved value verbatim instead of re-deriving a default. +func TestSnapshotShowsSavedEffortVerbatim(t *testing.T) { m := &model{ cfg: &config.Config{DefaultEffort: "high"}, input: newInput(), agentMessages: map[string][]llm.Message{}, clientView: clientPresentation{agentPresentations: map[string][]session.SnapshotEvent{}}, } - snapshot := session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root", Model: "model", Provider: "provider"}} + snapshot := session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root", Model: "model", Provider: "provider", Effort: "low"}} m.applyClientSnapshot(snapshot) - if m.displayEffort() != "high" { - t.Fatalf("inherited effort=%q, want high", m.displayEffort()) + if m.displayEffort() != "low" { + t.Fatalf("saved effort=%q, want low", m.displayEffort()) } snapshot.Cursor++ snapshot.Meta.Effort = "off" m.applyClientSnapshot(snapshot) - if m.displayEffort() != "" { + if m.displayEffort() != "off" { t.Fatalf("explicit off effort=%q", m.displayEffort()) } } diff --git a/internal/tui/effort.go b/internal/tui/effort.go index f7efd2c11..3cf857a24 100644 --- a/internal/tui/effort.go +++ b/internal/tui/effort.go @@ -7,8 +7,8 @@ import ( ) // defaultEfforts are the fallback levels when the provider doesn't advertise -// supported reasoning efforts; "" means off (parameter omitted from requests). -var defaultEfforts = []string{"", "low", "medium", "high"} +// supported reasoning efforts. "off" sends no reasoning parameter. +var defaultEfforts = []string{"off", "low", "medium", "high"} // effortCands completes /effort for models without advertised levels. var effortCands = []cand{ @@ -26,52 +26,17 @@ func (m *model) effortsFor() []string { } // effortsIn returns the effort cycle for a model id on a provider, using the -// given catalogs. Advertised levels win (prefixed by off ""); otherwise the +// given catalogs. Advertised levels win (prefixed by "off"); otherwise the // provider-agnostic defaults apply. func effortsIn(catalogs map[string]config.Catalog, provName, modelID string) []string { if c, ok := catalogs[provName]; ok { if levels := c.Efforts(modelID); len(levels) > 1 { - return levels // advertised: ["", "low", "medium", …] + return levels // advertised: ["off", "low", "medium", …] } } return defaultEfforts } -// DefaultEffortFor resolves the effort a new session should open on when the -// user hasn't pinned one (cfg.DefaultEffort == ""): "low" when the model -// advertises it (the intended default), else the lowest advertised level, else -// "" (off) when the catalog confirms the model doesn't reason, else "low" as a -// best guess when the model is entirely unknown (no catalog entry). pinned, -// when non-empty, is returned verbatim — an explicit config choice is honored -// as-is, even if the model later turns out not to support it (updateCatalogs -// resets the live session). -func DefaultEffortFor(catalogs map[string]config.Catalog, provName, modelID, pinned string) string { - if pinned == "off" { - return "" - } - if pinned != "" { - return pinned - } - // When the catalog has the entry, trust its advertised levels: prefer "low", - // else the lowest level, else off (the model doesn't reason). When the entry - // is missing entirely (unknown model/provider), fall back to "low". - if c, ok := catalogs[provName]; ok { - if mi := c.Find(modelID); mi != nil { - levels := c.Efforts(modelID) // [""] for a non-reasoning model - if slices.Contains(levels, "low") { - return "low" - } - for _, e := range levels { - if e != "" { - return e - } - } - return "" // catalog confirms: no reasoning - } - } - return "low" // unknown model — best-guess default for a reasoning ecosystem -} - // nextEffort cycles cur to the following level in levels, wrapping; an // unknown cur resets to levels[0]. func nextEffort(levels []string, cur string) string { @@ -83,23 +48,10 @@ func nextEffort(levels []string, cur string) string { return levels[0] } -// effortLabel renders a level for display ("" shows as off). -func effortLabel(e string) string { - if e == "" { - return "off" - } - return e -} - -// parseEffort validates user input against levels ("off" maps to ""). +// parseEffort validates user input against levels. func parseEffort(levels []string, s string) (string, bool) { - if s == "off" { - return "", true - } - for _, e := range levels[1:] { - if s == e { - return e, true - } + if slices.Contains(levels, s) { + return s, true } return "", false } @@ -108,7 +60,7 @@ func parseEffort(levels []string, s string) (string, bool) { func effortCandsFor(levels []string) []cand { out := make([]cand, 0, len(levels)) for _, e := range levels { - out = append(out, cand{effortLabel(e), ""}) + out = append(out, cand{e, ""}) } return out } diff --git a/internal/tui/effort_test.go b/internal/tui/effort_test.go index 352ff74f9..ac12f8dbf 100644 --- a/internal/tui/effort_test.go +++ b/internal/tui/effort_test.go @@ -7,27 +7,27 @@ import ( ) func TestEffortCycleAndParse(t *testing.T) { - got := "" - for _, want := range []string{"low", "medium", "high", "", "low"} { + got := "off" + for _, want := range []string{"low", "medium", "high", "off", "low"} { got = nextEffort(defaultEfforts, got) if got != want { t.Fatalf("cycle: got %q want %q", got, want) } } - if nextEffort(defaultEfforts, "bogus") != "" { + if nextEffort(defaultEfforts, "bogus") != "off" { t.Fatal("unknown level should reset to off") } - if effortLabel("") != "off" || effortLabel("high") != "high" { - t.Fatal("labels") - } - for in, want := range map[string]string{"off": "", "low": "low", "high": "high"} { - if lv, ok := parseEffort(defaultEfforts, in); !ok || lv != want { + for _, in := range []string{"off", "low", "high"} { + if lv, ok := parseEffort(defaultEfforts, in); !ok || lv != in { t.Fatalf("parse %q: %q %v", in, lv, ok) } } if _, ok := parseEffort(defaultEfforts, "ultra"); ok { t.Fatal("invalid level accepted") } + if _, ok := parseEffort(defaultEfforts, ""); ok { + t.Fatal("blank is not an effort level") + } } func TestEffortCompletion(t *testing.T) { @@ -49,7 +49,7 @@ func TestEffortsForAdvertisedLevels(t *testing.T) { }}, }, } - if got := m.effortsFor(); len(got) != 4 || got[0] != "" || got[3] != "max" { + if got := m.effortsFor(); len(got) != 4 || got[0] != "off" || got[3] != "max" { t.Fatalf("advertised levels: %v", got) } if next := nextEffort(m.effortsFor(), "high"); next != "max" { @@ -59,10 +59,10 @@ func TestEffortsForAdvertisedLevels(t *testing.T) { t.Fatal("medium should be rejected for deepseek") } - // "none" collapses into off ("") + // "none" collapses into "off" m.clientView.modelID = "claude-opus-5" got := m.effortsFor() - if got[0] != "" || len(got) != 7 { + if got[0] != "off" || len(got) != 7 { t.Fatalf("claude levels: %v", got) } for _, e := range got { @@ -83,33 +83,3 @@ func TestEffortsForAdvertisedLevels(t *testing.T) { t.Fatalf("missing catalog should fall back to defaults: %v", got) } } - -// DefaultEffortFor picks "low" when the model advertises it, the lowest -// supported level otherwise, and off ("") for non-reasoning models — so a -// startup never opens on an effort the provider would reject. An explicit -// pinned value is honored verbatim, even if unsupported. -func TestDefaultEffortForModelAware(t *testing.T) { - cats := map[string]config.Catalog{ - "inference": {Models: []config.ModelInfoLite{ - {ID: "deepseek-v4-flash", ReasoningEfforts: []string{"low", "high", "max"}}, // no medium - {ID: "claude-opus-5", ReasoningEfforts: []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"}}, - {ID: "gemini-3.5-flash"}, // no reasoning_efforts - }}, - } - cases := []struct{ model, pinned, want string }{ - {"deepseek-v4-flash", "", "low"}, // low is supported → low - {"claude-opus-5", "", "low"}, // low is supported → low - {"gemini-3.5-flash", "", ""}, // non-reasoning → off (no parameter) - {"deepseek-v4-flash", "high", "high"}, // pinned honored - {"deepseek-v4-flash", "medium", "medium"}, // pinned honored even though unsupported - } - for _, c := range cases { - if got := DefaultEffortFor(cats, "inference", c.model, c.pinned); got != c.want { - t.Fatalf("DefaultEffortFor(%q, pinned=%q): got %q want %q", c.model, c.pinned, got, c.want) - } - } - // unknown provider → default-effort cycle's first non-off (low) - if got := DefaultEffortFor(map[string]config.Catalog{}, "elsewhere", "anything", ""); got != "low" { - t.Fatalf("unknown provider should fall back to low, got %q", got) - } -} diff --git a/packages/app/src/model-selection.tsx b/packages/app/src/model-selection.tsx index cd938ac1a..cecdfe736 100644 --- a/packages/app/src/model-selection.tsx +++ b/packages/app/src/model-selection.tsx @@ -67,7 +67,7 @@ export function EffortPicker({ view, root, connected }: ModelProps) { const catalog = useProviderCatalog(view.session.client, connected); const models = useMemo(() => catalogModels(catalog.data?.result, root.meta.provider), [catalog.data, root.meta.provider]); const levels = modelEfforts(models, root.meta.model); - const current = root.meta.effort || 'off'; + const current = root.meta.effort; return { if (!pending) setOpen(value); }} xstyle={styles.popup} trigger={} - {(ready || !providers.inventory.isPending) && updateSetup({ effort })} />} + {(ready || !providers.inventory.isPending) && updateSetup({ effort: effort || undefined })} />} diff --git a/packages/app/test/welcome.test.tsx b/packages/app/test/welcome.test.tsx index 8a4966da3..eda82a88f 100644 --- a/packages/app/test/welcome.test.tsx +++ b/packages/app/test/welcome.test.tsx @@ -155,7 +155,8 @@ it('keeps an unsupported saved effort visible and requires an explicit replaceme fireEvent.click(await screen.findByRole('menuitem', { name: 'Default' })); fireEvent.click(screen.getByRole('button', { name: 'Send first message' })); await waitFor(() => expect(f.raw.sessions.create).toHaveBeenCalledOnce()); - await waitFor(() => expect(f.raw.sessions.create).toHaveBeenCalledWith(expect.objectContaining({ effort: 'off' }))); + // "Default" clears the draft choice; the daemon resolves the effort at creation. + expect(f.raw.sessions.create.mock.calls[0]![0]).not.toHaveProperty('effort'); }); it('preserves the collapsed provider top spacing while expanded and restores centering on collapse', async () => { From b8cc56a48d781998784fc7ce1cc541bea2cd59fb Mon Sep 17 00:00:00 2001 From: Sam Heutmaker Date: Mon, 28 Sep 2026 16:38:51 -0700 Subject: [PATCH 10/67] more clean up --- apps/web/scripts/agents.mjs | 120 ++++ apps/web/scripts/directory-sidebar.mjs | 174 +++++ apps/web/scripts/fixtures/agents/index.html | 13 + apps/web/scripts/fixtures/agents/main.tsx | 72 ++ apps/web/scripts/multiple-hosts.mjs | 6 +- apps/web/scripts/settings.mjs | 43 ++ apps/web/scripts/sidebar.mjs | 9 +- apps/web/scripts/user-messages.mjs | 140 +++- cmd/whip/daemon.go | 64 +- cmd/whip/daemon_test.go | 147 +++- docs/agent-loop.md | 17 +- docs/backend-redesign-plan.md | 650 ++++++++++++++++++ docs/features.md | 28 +- docs/frontend.md | 93 ++- docs/models-providers.md | 44 +- docs/roadmap.md | 4 + docs/web-app.md | 21 +- internal/agent/agent.go | 76 +- internal/agent/compaction_route.go | 124 ++++ internal/agent/compaction_route_test.go | 356 ++++++++++ internal/agent/context_journal_test.go | 81 ++- internal/agent/model_accounting_test.go | 3 + internal/config/config.go | 11 +- internal/config/config_test.go | 38 + internal/daemon/agent_session.go | 3 +- internal/daemon/client_control.go | 13 +- .../daemon/client_control_compaction_test.go | 88 +++ internal/daemon/client_control_test.go | 124 ++++ internal/daemon/compaction_fallback_test.go | 168 +++++ internal/daemon/context_history_test.go | 5 + .../daemon/provider_client_behavior_test.go | 5 +- internal/daemon/provider_service.go | 41 +- internal/daemon/provider_service_test.go | 171 +++++ internal/daemon/recursive_runtime.go | 2 + internal/daemon/recursive_runtime_test.go | 6 + internal/daemon/spans.go | 10 +- internal/daemon/v2_sdk_test.go | 12 + internal/llm/openai.go | 13 +- internal/llm/openai_test.go | 10 +- internal/llm/subscription.go | 15 +- internal/session/title.go | 7 +- internal/session/title_admission_test.go | 2 +- internal/session/title_test.go | 10 +- internal/session/transcript_page_test.go | 47 ++ internal/session/transcript_test.go | 9 +- internal/tui/client_control_render.go | 2 +- internal/tui/client_control_render_test.go | 39 ++ packages/app/src/chat-activity-rows.ts | 63 +- packages/app/src/chat-activity.tsx | 10 +- packages/app/src/compaction-settings.tsx | 100 +++ packages/app/src/conversation-rows.ts | 33 +- packages/app/src/conversation.tsx | 40 +- packages/app/src/details/session-controls.tsx | 70 +- packages/app/src/session-search-dialog.tsx | 10 +- packages/app/src/session-sidebar.stylex.ts | 23 +- packages/app/src/session-sidebar.tsx | 352 ++++++---- packages/app/src/settings/agents.tsx | 93 +-- packages/app/src/settings/configuration.tsx | 41 +- packages/app/src/settings/navigation.ts | 5 +- packages/app/src/sidebar-state.ts | 33 + packages/app/src/timeline.tsx | 71 +- packages/app/src/trace-view.tsx | 5 + packages/app/test/chat-activity.test.tsx | 90 +++ .../test/conversation-history-errors.test.tsx | 108 ++- packages/app/test/inspector.test.tsx | 138 +++- .../app/test/multi-host-discovery.test.tsx | 6 +- packages/app/test/session-sidebar.test.tsx | 218 +++++- packages/app/test/session-top-bar.test.tsx | 4 +- packages/app/test/settings-agents.test.tsx | 38 +- .../app/test/settings-configuration.test.tsx | 106 ++- packages/app/test/sidebar-state.test.ts | 33 +- packages/app/test/timeline-reading.test.tsx | 106 +++ packages/app/test/trace-view.test.tsx | 17 + packages/ui/README.md | 10 +- packages/ui/src/overlays.tsx | 8 +- packages/ui/src/styles.stylex.ts | 10 +- packages/ui/stories/Activity.stories.tsx | 9 +- packages/ui/stories/Library.stories.tsx | 18 +- packages/ui/tests/browser.mjs | 99 +++ scripts/update-local.mjs | 3 +- 80 files changed, 4496 insertions(+), 610 deletions(-) create mode 100644 apps/web/scripts/agents.mjs create mode 100644 apps/web/scripts/directory-sidebar.mjs create mode 100644 apps/web/scripts/fixtures/agents/index.html create mode 100644 apps/web/scripts/fixtures/agents/main.tsx create mode 100644 docs/backend-redesign-plan.md create mode 100644 internal/agent/compaction_route.go create mode 100644 internal/agent/compaction_route_test.go create mode 100644 internal/daemon/client_control_compaction_test.go create mode 100644 internal/daemon/compaction_fallback_test.go create mode 100644 internal/tui/client_control_render_test.go create mode 100644 packages/app/src/compaction-settings.tsx diff --git a/apps/web/scripts/agents.mjs b/apps/web/scripts/agents.mjs new file mode 100644 index 000000000..f42b4483d --- /dev/null +++ b/apps/web/scripts/agents.mjs @@ -0,0 +1,120 @@ +import assert from 'node:assert/strict'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { build, preview } from 'vite'; +import react from '@vitejs/plugin-react'; +import stylex from '@stylexjs/unplugin'; +import { chromium, firefox, expect } from '@playwright/test'; + +const web = fileURLToPath(new URL('../', import.meta.url)); +const results = process.env.WHIP_AGENT_RESULTS ?? '/tmp/whip-agent-dialog-results'; +await mkdir(results, { recursive: true }); +process.chdir(web); +const config = { + configFile: false, root: resolve(web, 'scripts/fixtures/agents'), logLevel: 'warn', + plugins: [stylex.vite({ useCSSLayers: { before: ['whip-reset'] }, runtimeInjection: false, + unstable_moduleResolution: { type: 'commonJS', rootDir: resolve(web, '../..') } }), react()], + build: { outDir: resolve(results, 'dist'), emptyOutDir: true, assetsInlineLimit: 0 }, + preview: { host: '127.0.0.1', port: 0, headers: { + 'Content-Security-Policy': "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; object-src 'none'; base-uri 'none'", + } }, +}; +await build(config); +const server = await preview(config); +const origin = 'http://127.0.0.1:' + server.httpServer.address().port; +const report = []; +try { + for (const [engine, browserType] of Object.entries({ chromium, firefox })) { + const browser = await browserType.launch(); + try { + const page = await browser.newPage(); + const errors = []; + page.on('pageerror', error => errors.push(error.message)); + await page.addInitScript(() => { + window.cspErrors = []; + document.addEventListener('securitypolicyviolation', event => window.cspErrors.push(event.violatedDirective)); + }); + for (const scenario of [ + { name: 'dark', width: 1440, height: 1000 }, + { name: 'light', width: 1440, height: 1000, theme: 'light' }, + { name: 'laptop', width: 1280, height: 800 }, + { name: 'tablet', width: 768, height: 1024, theme: 'light' }, + { name: 'phone', width: 390, height: 844 }, + { name: 'narrow', width: 320, height: 640, theme: 'light' }, + { name: 'large-text', width: 800, height: 900, size: 20 }, + { name: 'narrow-large-text', width: 320, height: 640, size: 20 }, + ]) { + await page.setViewportSize({ width: scenario.width, height: scenario.height }); + await page.goto(origin + '/?theme=' + (scenario.theme ?? 'dark') + '&size=' + (scenario.size ?? 13)); + const trigger = page.getByRole('button', { name: 'New agent', exact: true }); + await trigger.click(); + const dialog = page.getByRole('dialog', { name: 'New agent' }); + await expect(page.locator('html')).toHaveAttribute('data-theme', scenario.theme ?? 'dark'); + await expect(dialog).toHaveCSS('font-size', (scenario.size ?? 13) + 'px'); + const modules = dialog.getByRole('group', { name: 'Host modules', exact: true }); + await expect(modules.getByRole('checkbox')).toHaveCount(14); + await expect(dialog.getByRole('group', { name: 'Capabilities', exact: true }).getByRole('checkbox')).toHaveCount(6); + await page.evaluate(() => document.fonts.ready); + const nameInput = dialog.getByRole('textbox', { name: 'Agent Name', exact: true }); + await expect(nameInput).toBeFocused(); + const proseFont = await dialog.getByRole('textbox', { name: 'Persona' }).evaluate(element => getComputedStyle(element).fontFamily); + await expect(nameInput).toHaveCSS('font-family', proseFont); + await nameInput.fill('release-notes'); + await dialog.getByRole('textbox', { name: 'Persona' }).fill('You write release notes for the engineering team.'); + await dialog.getByRole('textbox', { name: 'Rules' }).fill('Cite commits.\nGroup changes by impact.'); + await modules.getByRole('checkbox', { name: 'context', exact: true }).click(); + await modules.getByRole('checkbox', { name: 'files', exact: true }).click(); + const geometry = await dialog.evaluate(element => { + const bounds = element.getBoundingClientRect(); + const fieldsets = [...element.querySelectorAll('fieldset')]; + return { + width: bounds.width, height: bounds.height, + overflow: element.scrollWidth > element.clientWidth, + crushed: fieldsets.some(fieldset => fieldset.querySelector('p').getBoundingClientRect().width < fieldset.clientWidth - 2), + clipped: [...element.querySelectorAll('label')].some(label => { + const rect = label.getBoundingClientRect(); + return rect.left < bounds.left || rect.right > bounds.right || label.scrollWidth > label.clientWidth + 1; + }), + }; + }); + assert.ok(!geometry.overflow && !geometry.crushed && !geometry.clipped, JSON.stringify({ scenario, geometry })); + assert.equal(geometry.width, Math.min(800, scenario.width - 32), 'Agent editor should use the wider desktop width without overflowing small screens'); + if (scenario.width >= 1280) assert.ok(geometry.height < 740, 'Agent editor should fit a laptop viewport without shrinking text'); + await dialog.getByRole('heading').scrollIntoViewIfNeeded(); + await page.screenshot({ path: resolve(results, engine + '-' + scenario.name + '.png') }); + const submit = dialog.getByRole('button', { name: 'Register agent', exact: true }); + if (scenario.width >= 1280) await expect(submit).toBeInViewport({ ratio: 1 }); + await submit.scrollIntoViewIfNeeded(); + await expect(submit).toBeInViewport(); + await page.screenshot({ path: resolve(results, engine + '-' + scenario.name + '-bottom.png') }); + const options = dialog.getByRole('button', { name: 'More options' }); + await options.focus(); + await options.press('Enter'); + await expect(options).toHaveAttribute('aria-expanded', 'true'); + await dialog.getByRole('textbox', { name: 'Project files' }).fill('AGENTS.md, CLAUDE.md'); + await dialog.getByRole('switch', { name: 'Goal loop', exact: true }).click(); + await submit.scrollIntoViewIfNeeded(); + await expect(submit).toBeInViewport(); + assert.ok(await dialog.evaluate(element => element.scrollWidth <= element.clientWidth), 'Expanded options overflow'); + await page.screenshot({ path: resolve(results, engine + '-' + scenario.name + '-expanded.png') }); + await options.click(); + await dialog.getByRole('button', { name: 'Register agent', exact: true }).click(); + await expect(dialog.getByRole('status')).toContainText('Registered release-notes'); + await page.keyboard.press('Escape'); + await expect(dialog).toBeHidden(); + await expect(trigger).toBeFocused(); + await expect(page.getByRole('list', { name: 'Agent definitions' })).toContainText('release-notes'); + await trigger.click(); + await expect(dialog.getByRole('textbox', { name: 'Agent Name', exact: true })).toBeFocused(); + await page.keyboard.press('Escape'); + await expect(dialog).toBeHidden(); + assert.deepEqual(await page.evaluate(() => window.cspErrors), []); + report.push({ engine, scenario: scenario.name, ...geometry }); + } + assert.deepEqual(errors, []); + } finally { await browser.close(); } + } + await writeFile(resolve(results, 'report.json'), JSON.stringify(report, null, 2)); + console.log('Agent dialog browser checks passed:', results); +} finally { await new Promise(resolve => server.httpServer.close(resolve)); } diff --git a/apps/web/scripts/directory-sidebar.mjs b/apps/web/scripts/directory-sidebar.mjs new file mode 100644 index 000000000..6097e216b --- /dev/null +++ b/apps/web/scripts/directory-sidebar.mjs @@ -0,0 +1,174 @@ +import assert from 'node:assert/strict'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { chromium, firefox } from '@playwright/test'; +import { createWhipClient } from '../../../packages/sdk/dist/index.js'; +import { eventually, startFixture } from '../../../packages/sdk/scripts/fixture.mjs'; + +// Focused, isolated coverage of the shared desktop/web directory-first sidebar. +const directory = process.env.WHIP_WEB_DIRECTORY_RESULTS ?? '/tmp/whip-directory-sidebar-results'; +await mkdir(directory, { recursive: true }); +const origin = fixture => fixture.info.endpoint.replace(/^ws/, 'http').replace('/api/v3/ws', ''); +const assertSessionGap = async (scope, height) => { + const links = scope.locator('[data-sidebar-session] a'); + const first = await links.nth(0).boundingBox(), second = await links.nth(1).boundingBox(); + assert.equal(first.height, height, 'Session targets retain their full height'); + assert.equal(second.y - (first.y + first.height), 1, 'Adjacent session backgrounds have a 1px gap'); +}; +for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(',')) { + const fixtures = [], clients = [], errors = [], frames = [], checks = []; + let browser; + try { + const local = await startFixture(); fixtures.push(local); + const remote = await startFixture({ allowedOrigins: [origin(local)] }); fixtures.push(remote); + for (const fixture of fixtures) { + const client = createWhipClient({ endpoint: fixture.info.endpoint, clientId: 'directory-sidebar', clientKind: 'human' }); + clients.push(client); await client.connect(); + } + const shared = join(local.directory, 'whip'), other = join(local.directory, 'rlm-new'); + await mkdir(shared); await mkdir(other); + const create = async (client, cwd, title) => { + const receipt = await client.sessions.create({ cwd, model: 'model', provider: 'provider' }).result(); + assert.equal(receipt.status, 'succeeded'); + const root = receipt.result.root_id; + await client.session(root).rename(title).result(); return root; + }; + await create(clients[0], other, 'Explore repo with subagents'); + await new Promise(resolve => setTimeout(resolve, 1100)); + const remoteRoot = await create(clients[1], shared, 'This is a remote session'); + await new Promise(resolve => setTimeout(resolve, 1100)); + const localRoot = await create(clients[0], shared, 'Map Whip backend architecture'); + const config = await clients[0].configuration.get(); + await clients[0].configuration.update({ revision: config.revision, remote_hosts: [{ id: 'mm', name: 'mm', url: origin(remote), runtime_id: remote.info.runtime_id, connect_on_launch: true }] }); + browser = await ({ chromium, firefox }[name]).launch(); + const context = await browser.newContext({ viewport: { width: 1440, height: 960 }, reducedMotion: 'reduce' }); + const page = await context.newPage(); + page.on('pageerror', error => errors.push(error.message)); + page.on('websocket', socket => socket.on('framesent', ({ payload }) => { try { frames.push({ endpoint: socket.url(), ...JSON.parse(String(payload)) }); } catch {} })); + await page.goto(origin(local) + '/h/' + local.info.runtime_id + '/s/' + localRoot); + const sidebar = page.locator('aside[aria-label="Session navigation"]'); + const row = (runtime, cwd) => sidebar.locator('[data-sidebar-directory][data-sidebar-runtime="' + runtime + '"][data-sidebar-directory="' + cwd + '"]'); + const session = (runtime, root) => sidebar.locator('[data-sidebar-session="' + root + '"][data-sidebar-runtime="' + runtime + '"]'); + const remoteRow = row(remote.info.runtime_id, shared), localRow = row(local.info.runtime_id, shared); + await remoteRow.waitFor(); await localRow.waitFor(); + await page.getByLabel('Message WHIP', { exact: true }).waitFor(); + const order = await sidebar.locator('[data-sidebar-directory]').evaluateAll(nodes => nodes.slice(0, 3).map(node => [node.dataset.sidebarRuntime, node.dataset.sidebarDirectory])); + assert.deepEqual(order, [[local.info.runtime_id, shared], [remote.info.runtime_id, shared], [local.info.runtime_id, other]]); + assert.equal(await sidebar.getByRole('region', { name: 'Local sessions', exact: true }).count(), 0); + assert.equal(await remoteRow.getByRole('button', { name: 'mm · Connected · ' + shared, exact: true }).count(), 1); + assert.equal(await sidebar.locator('[data-sidebar-directory] .lucide-folder, [data-sidebar-directory] .lucide-folder-open, [data-sidebar-directory] .lucide-globe').count(), 0); + await remoteRow.getByRole('button', { name: shared, exact: true }).click(); + assert.equal(await session(remote.info.runtime_id, remoteRoot).count(), 0); + assert.equal(await session(local.info.runtime_id, localRoot).count(), 1); + await clients[1].session(remoteRoot).rename('Remote update while collapsed').result(); + await page.waitForTimeout(2300); + assert.equal(await remoteRow.getByRole('button', { name: shared, exact: true }).getAttribute('aria-expanded'), 'false'); + await remoteRow.getByRole('button', { name: shared, exact: true }).click(); + await session(remote.info.runtime_id, remoteRoot).getByRole('link').click(); + await eventually(() => new URL(page.url()).pathname.includes(remote.info.runtime_id)); + assert.equal(await session(remote.info.runtime_id, remoteRoot).getByRole('link').getAttribute('aria-current'), 'page'); + checks.push('mixed recency, exact host/path identity, scoped collapse and remote selection'); + + const resize = page.getByRole('separator', { name: 'Resize session navigation' }); + for (const theme of ['light', 'dark', 'claude-code', 'cobalt2']) { + await page.evaluate(id => localStorage.setItem('whip.appearance.theme.v1', JSON.stringify({ version: 1, id })), theme); + await page.reload(); await remoteRow.waitFor(); + for (const [width, key] of [[256, 'Home'], [420, 'End']]) { + await resize.focus(); await page.keyboard.press(key); + await eventually(async () => Math.round((await sidebar.boundingBox()).width) === width); + assert.equal(await sidebar.getByLabel('Saved sessions', { exact: true }).evaluate(node => node.scrollWidth > node.clientWidth), false); + const centers = await remoteRow.locator(':scope > button, :scope > a').evaluateAll(nodes => nodes.map(node => { const box = node.getBoundingClientRect(); return box.y + box.height / 2; })); + assert.ok(Math.max(...centers) - Math.min(...centers) < 1, 'Directory controls must share a centerline'); + const hostTrigger = remoteRow.getByRole('button', { name: 'mm · Connected · ' + shared, exact: true }); + await hostTrigger.focus(); await page.keyboard.press('Enter'); + const details = page.getByRole('dialog', { name: /^mm Connected/ }); + await details.waitFor(); + assert.equal(await details.getByText(shared, { exact: true }).count(), 1); + const geometry = await details.evaluate(node => { + const action = node.querySelector('button'), rect = node.getBoundingClientRect(), css = getComputedStyle(node); + return { width: rect.width, left: rect.left, right: rect.right, overflow: node.scrollWidth > node.clientWidth, + border: css.borderTopWidth, align: getComputedStyle(action).justifyContent, + titleMargin: getComputedStyle(node.querySelector('h2')).marginBlockStart, side: node.dataset.side }; + }); + assert.ok(geometry.width <= 300 && geometry.left >= 0 && geometry.right <= 1440); + assert.equal(geometry.overflow, false); assert.equal(geometry.border, '1px'); assert.equal(geometry.align, 'flex-start'); + assert.equal(geometry.titleMargin, '0px'); assert.equal(geometry.side, 'right'); + await page.screenshot({ path: join(directory, name + '-' + theme + '-' + width + '.png') }); + await page.keyboard.press('Escape'); await details.waitFor({ state: 'hidden' }); + assert.ok(await hostTrigger.evaluate(node => node === document.activeElement)); + } + } + checks.push('256/420 px, light/dark/Claude Code/colorful themes, no overflow and aligned targets'); + // Restart only this isolated remote fixture, never the developer's daemon. + await remote.crashAndRestart({ beforeRestart: async () => { + await remoteRow.getByRole('button', { name: /mm · (Reconnecting|Offline)/ }).waitFor(); + assert.equal(await session(remote.info.runtime_id, remoteRoot).count(), 1); + assert.equal(await session(local.info.runtime_id, localRoot).count(), 1); + await page.screenshot({ path: join(directory, name + '-offline.png') }); + } }); + await remoteRow.getByRole('button', { name: 'mm · Connected · ' + shared, exact: true }).waitFor(); + checks.push('transport loss retains rows with truthful status and reconnect restores identity'); + + // A directory can cross hosts in the order without displacing the reading anchor. + let newest; + for (let index = 0; index < 42; index++) newest = await create(clients[0], shared, 'Session ' + index); + await session(local.info.runtime_id, newest).waitFor(); + const more = sidebar.locator('button[data-sidebar-runtime="' + local.info.runtime_id + '"]').filter({ hasText: /^More$/ }); + await more.waitFor(); + const sessionLinks = sidebar.locator('[data-sidebar-session] a'); + await session(local.info.runtime_id, newest).getByRole('link').click(); + await eventually(async () => await sessionLinks.nth(0).getAttribute('aria-current') === 'page'); + await sessionLinks.nth(1).hover(); + await assertSessionGap(sidebar, 28); + await page.screenshot({ path: join(directory, name + '-session-gap.png') }); + checks.push('active and hovered sessions stay separated by 1px without shrinking targets'); + for (let count = 0; count < 4; count++) await more.click(); + const saved = sidebar.getByLabel('Saved sessions', { exact: true }); + await saved.evaluate(node => { node.scrollTop = 240; }); + await page.waitForTimeout(150); + assert.equal(await saved.evaluate(node => node.scrollTop), 240, 'Anchor fixture needs space below the reading position'); + const anchor = await saved.evaluate(node => { + const top = node.getBoundingClientRect().top; + const row = [...node.querySelectorAll('[data-sidebar-session]')].find(row => row.getBoundingClientRect().bottom > top); + return { id: row.dataset.sidebarSession, runtime: row.dataset.sidebarRuntime, y: row.getBoundingClientRect().top - top }; + }); + await new Promise(resolve => setTimeout(resolve, 1100)); + await create(clients[1], shared, 'New remote session above reading position'); + await page.waitForTimeout(2400); + const after = await session(anchor.runtime, anchor.id).evaluate(node => node.getBoundingClientRect().top - node.closest('[aria-label="Saved sessions"]').getBoundingClientRect().top); + assert.ok(Math.abs(after - anchor.y) < 2, 'Cross-host directory reorder must preserve the reading anchor: ' + JSON.stringify({ anchor, after, scroll: await saved.evaluate(node => node.scrollTop) })); + await saved.evaluate(node => { node.scrollTop = 0; }); + await page.waitForTimeout(150); + assert.equal(await sidebar.locator('[data-sidebar-directory]').first().getAttribute('data-sidebar-runtime'), remote.info.runtime_id); + checks.push('cross-host directory reorder preserves the visible session anchor'); + + await page.setViewportSize({ width: 390, height: 844 }); + await page.getByRole('button', { name: 'Open navigation', exact: true }).click(); + const sheet = page.getByRole('dialog', { name: 'WHIP', exact: true }); + await sheet.getByLabel('Saved sessions', { exact: true }).evaluate(node => { node.scrollTop = 0; }); + await page.waitForTimeout(150); + await assertSessionGap(sheet, 44); + const directoryButtons = sheet.locator('[data-sidebar-directory] > button'); + assert.ok((await directoryButtons.first().boundingBox()).height >= 44); + assert.equal(await sheet.getByLabel('Saved sessions', { exact: true }).evaluate(node => node.scrollWidth > node.clientWidth), false); + const mobileHost = sheet.getByRole('button', { name: 'mm · Connected · ' + shared, exact: true }); + assert.ok((await mobileHost.boundingBox()).height >= 44); + await mobileHost.click(); + const mobileDetails = page.getByRole('dialog', { name: /^mm Connected/ }); + await mobileDetails.waitFor(); + assert.equal(await mobileDetails.evaluate(node => node.scrollWidth > node.clientWidth), false); + const mobileBox = await mobileDetails.boundingBox(); + assert.ok(mobileBox.x >= 0 && mobileBox.x + mobileBox.width <= 390); + assert.ok((await mobileDetails.getByRole('button', { name: 'Manage servers' }).boundingBox()).height >= 44); + await page.screenshot({ path: join(directory, name + '-mobile.png') }); + await page.keyboard.press('Escape'); + checks.push('mobile-web sheet preserves touch targets and avoids horizontal overflow'); + assert.ok(frames.filter(frame => frame.method === 'sessions.summaries').every(frame => frame.params.root_ids.length <= 32)); + assert.equal(errors.length, 0, errors.join('\n')); + await writeFile(join(directory, name + '-results.json'), JSON.stringify({ checks, errors }, null, 2)); + console.log(name + ': ' + checks.join('; ')); + } finally { + await browser?.close(); for (const client of clients) client.close(); + for (const fixture of fixtures.reverse()) await fixture.close(); + } +} diff --git a/apps/web/scripts/fixtures/agents/index.html b/apps/web/scripts/fixtures/agents/index.html new file mode 100644 index 000000000..c39410c39 --- /dev/null +++ b/apps/web/scripts/fixtures/agents/index.html @@ -0,0 +1,13 @@ + + + + + + + Agents settings preview + + +
+ + + diff --git a/apps/web/scripts/fixtures/agents/main.tsx b/apps/web/scripts/fixtures/agents/main.tsx new file mode 100644 index 000000000..2c34fa7e3 --- /dev/null +++ b/apps/web/scripts/fixtures/agents/main.tsx @@ -0,0 +1,72 @@ +// Actual agent editor with the full host catalog; no daemon or registration side effects. +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { defaultDisplayPreferences, displayStorageKey, initializeTheme, ThemeProvider, UIProvider } from '@whip/ui'; +import type { WhipClient } from '@whip/sdk'; +import type { Definition } from '@whip/sdk/agents'; +import type { ReactNode } from 'react'; +import * as stylex from '@stylexjs/stylex'; +import { scale } from '@whip/ui/tokens.stylex'; +import '@whip/ui/fonts.css'; +import '@whip/ui/reset.css'; +import { RuntimeContext } from '../../../../../packages/app/src/context'; +import type { AppRuntime } from '../../../../../packages/app/src/runtime'; +import { AgentsSettings } from '../../../../../packages/app/src/settings/agents'; + +const query = new URLSearchParams(location.search); +localStorage.setItem('whip.appearance.theme.v1', JSON.stringify({ version: 1, id: query.get('theme') ?? 'dark' })); +localStorage.setItem(displayStorageKey, JSON.stringify({ version: 1, display: { ...defaultDisplayPreferences, uiSize: Number(query.get('size') ?? 13) } })); +initializeTheme({ storage: localStorage }); + +const coding: Definition = { + id: 'coding', + instructions: { persona: 'You are a coding agent.', rules: 'Rules.', project_files: ['CLAUDE.md'], skill_discovery: true, standing_instructions: true }, + modules: ['context', 'files', 'shell', 'browser', 'computer', 'models', 'agents', 'messages', 'mcp', 'state', 'artifacts', 'schedules', 'permissions', 'user'], capabilities: ['read', 'write', 'shell', 'browser', 'computer', 'mcp'], + model: { model: '', provider: '', effort: '' }, compaction: { model: '', provider: '', threshold: 0 }, mcp: { servers: null }, + tools: null, output: null, children: {}, surface: { auto_title: true, goal_loop: true }, hooks: null, +}; +const triage: Definition = { ...coding, id: 'support-triage', instructions: { ...coding.instructions, persona: 'You triage tickets.', project_files: null }, modules: ['context', 'files'], capabilities: ['read'], surface: { auto_title: true, goal_loop: false } }; + +const registered = [{ id: 'support-triage', revision: 'b'.repeat(64), built_in: false, registered_by: 'app', created_at: '2026-09-11T00:00:00Z' }]; +const client = { + getSnapshot: () => ({ state: 'connected', info: { runtime_id: 'host-a' } }), + supports: () => true, + agents: { + list: async () => ({ items: [{ id: 'coding', revision: '', built_in: true, registered_by: '', created_at: '' }, ...registered] }), + get: async (id: string) => ({ definition: id === 'coding' ? coding : triage, revision: id === 'coding' ? '' : 'b'.repeat(64), built_in: id === 'coding', registered_by: '', created_at: '' }), + register: async (definition: Definition) => { + registered.push({ id: definition.id, revision: 'c'.repeat(64), built_in: false, registered_by: 'app', created_at: '2026-09-11T00:00:01Z' }); + return { id: definition.id, revision: 'c'.repeat(64), created: true }; + }, + }, +} as unknown as WhipClient; + +const queries = new QueryClient({ defaultOptions: { queries: { retry: false, gcTime: 0 } } }); +const runtime = { queries, report: () => {}, getSnapshot: () => ({ commands: [] }), subscribe: () => () => {} } as unknown as AppRuntime; + +function Harness(children: ReactNode) { + return ( + + + + {children} + + + + ); +} + +const styles = stylex.create({ page: { maxWidth: 960, marginInline: 'auto', padding: scale.space4 } }); + +const element = document.getElementById('root'); +if (!element) throw new Error('root missing'); +createRoot(element).render( + + {Harness( +
+ +
, + )} +
, +); diff --git a/apps/web/scripts/multiple-hosts.mjs b/apps/web/scripts/multiple-hosts.mjs index aa5bb9ee7..212f4a869 100644 --- a/apps/web/scripts/multiple-hosts.mjs +++ b/apps/web/scripts/multiple-hosts.mjs @@ -107,7 +107,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' for (const host of hosts.slice(1)) { await manage(); await addHost(host); - await page.getByRole('region', { name: `${host.name} sessions`, exact: true }).getByRole('link', { name: `Shared title ${host.name}`, exact: true }).waitFor(); + await page.locator('[data-sidebar-runtime="' + host.runtimeId + '"]').getByRole('link', { name: `Shared title ${host.name}`, exact: true }).waitFor(); } const profiles = (await hosts[0].client.configuration.get()).remote_hosts; assert.deepEqual(profiles.map(profile => profile.name), ['Remote A', 'Remote B']); @@ -115,7 +115,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' const peer = await browser.newContext(); const peerPage = await peer.newPage(); await peerPage.goto(origin(local)); - for (const host of hosts) await peerPage.getByRole('region', { name: `${host.name} sessions`, exact: true }).waitFor(); + for (const host of hosts) await peerPage.locator('[data-sidebar-directory][data-sidebar-runtime="' + host.runtimeId + '"]').waitFor(); await peer.close(); checks.push('UI saves two verified profiles only in Local config; a fresh browser discovers all three hosts'); @@ -148,7 +148,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' // Build the mixed workspace through ordinary sidebar and tab-menu actions. for (const host of hosts) { - await page.getByRole('region', { name: `${host.name} sessions`, exact: true }).getByRole('link', { name: `Shared title ${host.name}`, exact: true }).click(); + await page.locator('[data-sidebar-runtime="' + host.runtimeId + '"]').getByRole('link', { name: `Shared title ${host.name}`, exact: true }).click(); await ready(host.root); } await action(hosts[0].root, 'Split right'); diff --git a/apps/web/scripts/settings.mjs b/apps/web/scripts/settings.mjs index ae7143c50..d5738b614 100644 --- a/apps/web/scripts/settings.mjs +++ b/apps/web/scripts/settings.mjs @@ -46,6 +46,7 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await composer.fill('Keep this unsent draft while changing settings.'); const before = await page.evaluate(() => sessionStorage.getItem('whip.web.workspace.v3')); await page.locator('#whip-settings-link').click(); + await category('Appearance').click(); await expect(page.getByRole('heading', { name: 'Appearance', exact: true })).toBeVisible(); await expect(page.locator('#whip-session-navigation')).toHaveCount(0); await expect(page.getByRole('tablist')).toHaveCount(0); @@ -108,6 +109,43 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await category(label).click(); await expect(page.getByRole('heading', { name: label, exact: true })).toBeVisible(); await expect(page.getByRole('button', { name: /^Attention ·/ })).toHaveCount(0); + if (label === 'Agents & execution') { + await expect(page.locator('#compact_model')).toContainText('Automatic'); + await expect(page.locator('#compact_percent')).toContainText('50%'); + await expect(page.getByRole('button', { name: 'Custom summary model', exact: true })).toBeHidden(); + await page.getByRole('button', { name: 'Advanced compaction settings', exact: true }).click(); + await select('Summary model mode', 'Custom'); + await page.getByRole('button', { name: 'Custom summary model', exact: true }).click(); + await page.getByRole('option', { name: 'settings-model · openrouter', exact: true }).click(); + await select('Compaction timing', 'Custom'); + const percentage = page.getByRole('spinbutton', { name: 'Context window percentage', exact: true }); + await percentage.fill('65'); + await page.getByRole('button', { name: 'Save host defaults', exact: true }).click(); + await expect(page.getByRole('button', { name: 'Save host defaults', exact: true })).toBeDisabled(); + let savedCompaction = JSON.parse((await readFile(join(fixture.directory, 'home', 'config.json'), 'utf8')).replace(/^\/\/[^\n]*\n/gm, '')); + assert.equal(savedCompaction.compactModel, 'settings-model'); + assert.equal(savedCompaction.compactProvider, 'openrouter'); + assert.equal(savedCompaction.compactPct, 65); + await auditServers('main'); + await page.locator('#compact_model').scrollIntoViewIfNeeded(); + await page.screenshot({ path: join(results, engine + '-compaction-custom.png') }); + await select('Summary model mode', 'Automatic'); + await select('Compaction timing', 'Automatic · 50%'); + await page.getByRole('button', { name: 'Save host defaults', exact: true }).click(); + await expect(page.getByRole('button', { name: 'Save host defaults', exact: true })).toBeDisabled(); + savedCompaction = JSON.parse((await readFile(join(fixture.directory, 'home', 'config.json'), 'utf8')).replace(/^\/\/[^\n]*\n/gm, '')); + assert.equal(savedCompaction.compactModel ?? '', ''); + assert.equal(savedCompaction.compactProvider ?? '', ''); + assert.equal(savedCompaction.compactPct ?? 0, 0); + await page.getByRole('button', { name: 'Advanced compaction settings', exact: true }).click(); + await page.setViewportSize({ width: 390, height: 844 }); + await expect(page.locator('#compact_model')).toContainText('Automatic'); + assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'Compaction settings overflow on mobile'); + await page.locator('#compact_model').scrollIntoViewIfNeeded(); + await page.screenshot({ path: join(results, engine + '-compaction-automatic-narrow.png') }); + await page.setViewportSize({ width: 1440, height: 1080 }); + checks.push('automatic compaction, connected custom model/provider, threshold, reset, and mobile reflow'); + } if (label === 'Servers') { await expect(page.getByRole('heading', { name: 'Servers', exact: true })).toHaveCount(1); await expect(page.getByRole('textbox', { name: 'Server address' })).toHaveCount(0); @@ -185,6 +223,11 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await page.getByRole('option', { name: 'Claude Code Dark', exact: true }).click(); await expect(page.locator('html')).toHaveAttribute('data-theme', 'claude-code'); await page.screenshot({ path: join(results, `${engine}-appearance-dark.png`) }); + await category('Agents & execution').click(); + await expect(page.locator('#compact_model')).toContainText('Automatic'); + await page.locator('#compact_model').scrollIntoViewIfNeeded(); + await auditServers('main'); + await page.screenshot({ path: join(results, engine + '-compaction-automatic-dark.png') }); await category('Servers').click(); await auditServers('main'); await page.screenshot({ path: join(results, `${engine}-servers-dark.png`) }); diff --git a/apps/web/scripts/sidebar.mjs b/apps/web/scripts/sidebar.mjs index b0bb19b68..84b11cdf6 100644 --- a/apps/web/scripts/sidebar.mjs +++ b/apps/web/scripts/sidebar.mjs @@ -62,6 +62,8 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await eventually(async () => await sidebar().locator(`[data-sidebar-session][data-sidebar-cwd="${paths[0]}"]`).count() === 14); const header = sidebar().locator('[data-sidebar-header]'); const edge = sidebar().locator('[data-sidebar-scroll-edge]'); + // The shell's entrance transition can still be settling after its first catalog. + await page.evaluate(async () => { await Promise.all(document.getAnimations().filter(animation => animation.effect?.getComputedTiming().iterations !== Infinity).map(animation => animation.finished.catch(() => {}))); }); const headerBefore = await header.boundingBox(); const searchBefore = await sidebar().getByRole('button', { name: 'Search sessions', exact: true }).boundingBox(); assert.equal(await edge.evaluate(node => getComputedStyle(node).opacity), '0'); @@ -85,11 +87,12 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await less.click(); await saved().evaluate(node => { node.scrollTop = 0; }); await more().waitFor(); + await eventually(async () => (await sidebar().locator('[data-sidebar-session]').count()) === 17, { description: 'virtual rows settle after Less and scroll reset' }); assert.equal(await sidebar().locator(`[data-sidebar-session][data-sidebar-cwd="${paths[0]}"]`).count(), 7); assert.equal(await sidebar().locator('[data-sidebar-session]').count(), 17); checks.push('seven sessions per directory, keyboard More, and Less'); - const action = id => page.locator(`[data-sidebar-session="${id}"]`).getByRole('button'); + const action = id => page.locator(`[data-sidebar-session="${id}"]`).getByRole('button', { name: /^Actions for / }); const caret = path => group(path).locator('[data-directory-caret]'); const opacity = locator => locator.evaluate(node => getComputedStyle(node).opacity); const rowFill = id => page.locator(`[data-sidebar-session="${id}"] a`).evaluate(node => getComputedStyle(node.parentElement).backgroundColor); @@ -220,8 +223,8 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' const after = await page.locator(`[data-sidebar-session="${anchor.id}"]`).evaluate(node => node.getBoundingClientRect().top - node.closest('[aria-label="Saved sessions"]').getBoundingClientRect().top); assert.ok(Math.abs(after - anchor.y) < 2, `Reading anchor moved: ${anchor.y} -> ${after}`); await saved().evaluate(node => { node.scrollTop = node.scrollHeight; }); - await saved().getByRole('button', { name: 'Load more sessions' }).click(); - await eventually(async () => await saved().getByRole('button', { name: 'Load more sessions' }).count() === 0); + await saved().getByRole('button', { name: 'Load more sessions · Local' }).click(); + await eventually(async () => await saved().getByRole('button', { name: 'Load more sessions · Local' }).count() === 0); console.log(`${name}: completed workflow ${checks.length + 1}`); checks.push('catalog reorder preserves visible anchor; explicit load-more reaches later pages'); diff --git a/apps/web/scripts/user-messages.mjs b/apps/web/scripts/user-messages.mjs index c8c9b932e..b42761b29 100644 --- a/apps/web/scripts/user-messages.mjs +++ b/apps/web/scripts/user-messages.mjs @@ -1,13 +1,19 @@ import assert from 'node:assert/strict'; import { mkdir } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +import { readRendererManifest, verifyRenderer } from '../../../scripts/renderer-artifact.mjs'; import { chromium, firefox, expect } from '@playwright/test'; import { createWhipClient } from '../../../packages/sdk/dist/index.js'; import { startFixture, eventually } from '../../../packages/sdk/scripts/fixture.mjs'; +// The fixture gateway embeds internal/webassets/dist. Fail clearly instead of +// silently validating an old renderer after a frontend-only build. +const renderer = await readRendererManifest(fileURLToPath(new URL('../renderer-manifest.json', import.meta.url))); +await verifyRenderer(fileURLToPath(new URL('../../../internal/webassets/dist', import.meta.url)), renderer); const output = '/tmp/whip-user-message-results'; await mkdir(output, { recursive: true }); for (const [name, launcher] of Object.entries({ chromium, firefox })) { - const fixture = await startFixture(); + const fixture = await startFixture({ lifetimeMs: 8 * 60_000 }); const browser = await launcher.launch(); const client = createWhipClient({ endpoint: fixture.info.endpoint, clientId: crypto.randomUUID(), clientKind: 'human' }); let page; @@ -77,12 +83,13 @@ for (const [name, launcher] of Object.entries({ chromium, firefox })) { await fixture.release('thinking-first-token'); await expect(working).toContainText('Writing a response…'); assert.equal(await page.locator('[data-message-role="assistant"]').count(), 1, 'Response is streaming but unfinished'); + await expect(page.locator('[data-response-actions]')).toHaveCount(0); await bubble.hover(); await page.screenshot({ path: `${output}/${name}-light.png` }); await composer.fill('Queued while the response runs'); await composer.press('Enter'); - const queued = page.locator('[data-message-role="user"]').filter({ hasText: 'Queued while the response runs' }); - await queued.getByRole('status').filter({ hasText: 'Queued' }).waitFor(); + await expect(page.getByText('1 queued message', { exact: true })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Steer queued message: Queued while the response runs', exact: true })).toBeVisible(); const roles = await page.locator('[data-message-role]').evaluateAll(nodes => nodes.map(node => node.getAttribute('data-message-role'))); - assert.deepEqual(roles, ['user', 'assistant', 'user'], 'Queued message follows the current response'); + assert.deepEqual(roles, ['user', 'assistant'], 'Queued input stays in the queue lane until delivery'); await page.evaluate(() => localStorage.setItem('whip.appearance.theme.v1', JSON.stringify({ version: 1, id: 'dark' }))); await page.reload(); await composer.waitFor(); await user.waitFor(); assert.equal(await user.count(), 1, 'Reload reconstructs running user input from the inbox'); @@ -97,7 +104,7 @@ for (const [name, launcher] of Object.entries({ chromium, firefox })) { await eventually(async () => await composer.inputValue() === ''); } await eventually(async () => (await page.locator('[data-message-role="user"]').filter({ hasText: 'Same message' }).count()) === 2); - await eventually(async () => (await page.locator('[data-message-role="user"][data-message-id^="h:"]').count()) === 4); + await eventually(async () => (await page.locator('[data-message-role="user"][data-message-id^="h:"]').filter({ hasText: 'Same message' }).count()) === 2); await page.setViewportSize({ width: 390, height: 844 }); await eventually(async () => { await page.locator('[data-message-role="user"]').last().scrollIntoViewIfNeeded(); @@ -105,6 +112,7 @@ for (const [name, launcher] of Object.entries({ chromium, firefox })) { }); assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth), false); await page.screenshot({ path: `${output}/${name}-narrow.png` }); + await checkResponseActions({ page, browser, client, fixture, origin, name }); assert.deepEqual(errors, []); assert.deepEqual(await page.evaluate(() => window.__messageCsp), []); console.log(`${name}: immediate Sending, thinking before the first token, 7s caption rotation, trailer completion, pre-send bubble, running/reloaded input, exact-once completion, identical messages, hover/focus, right alignment, light/dark/narrow and CSP passed`); @@ -116,3 +124,125 @@ for (const [name, launcher] of Object.entries({ chromium, firefox })) { throw error; } finally { client.close(); await browser.close(); await fixture.close(); } } + +// Reuse the real daemon fixture: verify commands against persisted history, not +// just that a menu closes. Clipboard I/O is the only substituted platform edge. +async function checkResponseActions({ page, browser, client, fixture, origin, name }) { + await page.setViewportSize({ width: 1440, height: 960 }); + const created = await client.sessions.create({ cwd: fixture.directory, model: 'model', provider: 'provider' }).result(); + const rootId = created.result.root_id, session = client.session(rootId); + const first = 'Response footer fixture — keep this answer'; + await session.submit({ text: first }).result(); + await eventually(async () => (await session.history.page()).messages.filter(entry => entry.message?.role === 'assistant').length === 1); + await session.submit({ text: 'Later response — remove only this turn' }).result(); + await eventually(async () => (await session.history.page()).messages.filter(entry => entry.message?.role === 'assistant').length === 2); + const original = (await session.history.page()).messages; + const answer = original.find(entry => entry.message?.role === 'assistant'); + assert.ok(answer?.message.sent_at, 'Assistant timestamps are recorded on the host'); + const prefix = original.filter(entry => entry.seq <= answer.seq); + const url = origin + '/h/' + fixture.info.runtime_id + '/s/' + rootId; + await page.goto(url); + const reading = page.getByRole('region', { name: 'Conversation', exact: true }); + const footers = page.locator('[data-response-actions]'); + const footer = footers.first(); + const menuButton = footer.getByRole('button', { name: 'Response history actions' }); + const composer = page.getByLabel('Message WHIP', { exact: true }); + await expect(footers).toHaveCount(2); + assert.equal(Date.parse(await footer.locator('time').getAttribute('datetime')), Date.parse(answer.message.sent_at)); + assert.ok((await footer.locator('time').getAttribute('aria-label'))?.length > 10, 'Full date/time is accessible'); + await composer.focus(); await page.mouse.move(1, 1); + assert.equal(await footer.evaluate(node => getComputedStyle(node).opacity), '0'); + const before = await reading.evaluate(node => node.scrollTop); + await page.locator('[data-message-role="assistant"]').first().hover(); + assert.equal(await footer.evaluate(node => getComputedStyle(node).opacity), '1', 'Hovering the response reveals its footer'); + assert.equal(await reading.evaluate(node => node.scrollTop), before, 'Revealing controls preserves reading position'); + const geometry = await footer.boundingBox(); + const prose = await page.locator('[data-message-role="assistant"]').first().boundingBox(); + assert.ok(Math.abs(geometry.x - prose.x) < 2, 'Agent footer aligns to the prose left edge'); + await page.evaluate(() => { + window.__responseCopies = []; + Object.defineProperty(navigator, 'clipboard', { configurable: true, value: { + writeText: async text => { window.__responseCopies.push(text); }, + } }); + }); + await footer.getByRole('button', { name: 'Copy response', exact: true }).click(); + await expect(footer.getByRole('button', { name: 'Copied', exact: true })).toBeVisible(); + assert.deepEqual(await page.evaluate(() => window.__responseCopies), [answer.message.content]); + await page.mouse.move(1, 1); await menuButton.focus(); + assert.equal(await footer.evaluate(node => getComputedStyle(node).opacity), '1', 'Keyboard focus reveals controls'); + await page.keyboard.press('Enter'); + await expect(page.getByRole('menuitem', { name: 'Fork from here', exact: true })).toBeVisible(); + await page.mouse.move(1, 1); + assert.equal(await footer.evaluate(node => getComputedStyle(node).opacity), '1', 'Open menu preserves controls'); + await page.keyboard.press('Escape'); + await expect(menuButton).toBeFocused(); + + // A denied write belongs to this response; successful retry clears the error. + await page.evaluate(() => { navigator.clipboard.writeText = async () => { throw new Error('Clipboard blocked for this test'); }; }); + await footer.getByRole('button', { name: 'Copy response', exact: true }).click(); + await expect(page.getByText('Could not copy message', { exact: true })).toBeVisible(); + await footer.getByText('Error details', { exact: true }).click(); + await expect(page.getByText('Clipboard blocked for this test', { exact: true })).toBeVisible(); + await page.evaluate(() => { navigator.clipboard.writeText = async text => { window.__responseCopies.push(text); }; }); + await footer.getByRole('button', { name: 'Copy response', exact: true }).click(); + await expect(page.getByText('Clipboard blocked for this test', { exact: true })).toHaveCount(0); + + for (const theme of ['light', 'dark', 'claude-code']) { + await page.evaluate(id => localStorage.setItem('whip.appearance.theme.v1', JSON.stringify({ version: 1, id })), theme); + await page.reload(); await expect(footers).toHaveCount(2); + assert.equal(Date.parse(await footer.locator('time').getAttribute('datetime')), Date.parse(answer.message.sent_at)); + await menuButton.focus(); await page.keyboard.press('Enter'); + const menu = page.getByRole('menu'); + await expect(menu).toBeVisible(); + const box = await menu.boundingBox(); + assert.ok(box.x >= 0 && box.y >= 0 && box.x + box.width <= 1440 && box.y + box.height <= 960, 'Menu stays in the viewport'); + await page.screenshot({ path: output + '/' + name + '-response-' + theme + '.png' }); + await page.keyboard.press('Escape'); + } + await page.setViewportSize({ width: 390, height: 844 }); + await menuButton.focus(); await page.keyboard.press('Enter'); + const narrowMenu = await page.getByRole('menu').boundingBox(); + assert.ok(narrowMenu.x >= 0 && narrowMenu.x + narrowMenu.width <= 390, 'Narrow response menu does not overflow'); + assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth), false); + await page.screenshot({ path: output + '/' + name + '-response-narrow.png' }); + await page.keyboard.press('Escape'); + await page.setViewportSize({ width: 1440, height: 960 }); + + await menuButton.focus(); await page.keyboard.press('Enter'); + await page.getByRole('menuitem', { name: 'Fork from here', exact: true }).click(); + const forkDialog = page.getByRole('dialog', { name: /Fork/ }); + await forkDialog.getByRole('button', { name: 'Confirm fork', exact: true }).click(); + await eventually(() => !page.url().endsWith('/s/' + rootId)); + const forkId = new URL(page.url()).pathname.split('/s/')[1]?.split('/')[0]; + assert.ok(forkId && forkId !== rootId, 'Fork opens the new session'); + assert.deepEqual((await client.session(forkId).history.page()).messages.map(entry => entry.message), prefix.map(entry => entry.message), 'Fork includes selected response and no later records'); + assert.equal((await session.history.page()).messages.length, original.length, 'Fork leaves source history alone'); + + await page.goto(url); await expect(footers).toHaveCount(2); + await menuButton.focus(); await page.keyboard.press('Enter'); + await page.getByRole('menuitem', { name: 'Rewind to here…', exact: true }).click(); + const rewindDialog = page.getByRole('dialog', { name: /Rewind/ }); + assert.equal((await session.history.page()).messages.length, original.length, 'Rewind waits for confirmation'); + await rewindDialog.getByRole('button', { name: 'Confirm rewind', exact: true }).click(); + await expect(rewindDialog).toHaveCount(0); + assert.deepEqual((await session.history.page()).messages.map(entry => entry.message), prefix.map(entry => entry.message), 'Rewind retains selected response, removes only later history'); + await expect(footers).toHaveCount(1); + await menuButton.focus(); await page.keyboard.press('Enter'); + await expect(page.getByRole('menuitem', { name: 'Rewind to here…', exact: true })).toBeDisabled(); + await page.keyboard.press('Escape'); + + const touchContext = await browser.newContext({ viewport: { width: 390, height: 844 }, hasTouch: true }); + try { + const touch = await touchContext.newPage(); + await touch.goto(url); + const actions = touch.locator('[data-response-actions]').first(); + await expect(actions).toBeVisible(); + assert.equal(await actions.evaluate(node => getComputedStyle(node).opacity), '1', 'Touch controls are always available'); + const sizes = await actions.getByRole('button').evaluateAll(nodes => nodes.map(node => { const rect = node.getBoundingClientRect(); return [rect.width, rect.height]; })); + assert.ok(sizes.length >= 2 && sizes.every(([width, height]) => width >= 44 && height >= 44), 'Touch targets are at least 44px'); + await actions.getByRole('button', { name: 'Response history actions' }).tap(); + await expect(touch.getByRole('menuitem', { name: 'Fork from here', exact: true })).toBeVisible(); + await touch.screenshot({ path: output + '/' + name + '-response-touch.png' }); + } finally { await touchContext.close(); } + console.log(name + ': response date/copy/menu, hover/focus/touch, clipboard failure/retry, theme/reload/narrow, and real inclusive fork/rewind passed'); +} diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index ea3857ba9..9e4e13045 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -152,32 +152,7 @@ func runDaemon(ctx context.Context, args []string) error { resolved, _, resolveErr := resolveRuntimeModel(currentCfg, model, provider, providers) return resolved, resolveErr } - // Compaction defaults: the definition first, then host configuration. - compactName, compactProvider := definition.Compaction.Model, definition.Compaction.Provider - if compactName == "" { - compactName, compactProvider = runtimeCfg.CompactModel, runtimeCfg.CompactProvider - } - if compactName == "" { - compactName = config.DefaultCompactModel - } - if compact, _, resolveErr := resolveRuntimeModel(runtimeCfg, compactName, compactProvider, providers); resolveErr == nil { - ag.CompactClient = compact.Client - ag.CompactModel, ag.CompactProvider = compact.Model, compact.Provider - ag.CompactPricing = compact.Pricing - } else { - // Summaries fall back to the conversation's own model. Say so: - // silently folding on an expensive reasoning model cost a session - // 160 s per fold before anyone noticed the cheap model was unused. - config.LogEvent("compaction.fallback", fmt.Sprintf("compact model %q (provider %q) unavailable, summaries run on the conversation model: %v", compactName, compactProvider, resolveErr)) - } - ag.CompactThreshold = definition.Compaction.Threshold - if ag.CompactThreshold == 0 { - compactPct := runtimeCfg.CompactPct - if compactPct == 0 { - compactPct = config.DefaultCompactPct - } - ag.CompactThreshold = float64(min(max(compactPct, 10), 90)) / 100 - } + configureRuntimeCompaction(ag, runtimeCfg, definition.Compaction, providers) var mcpManager *mcp.Manager discovery := mcp.LoadMergedFiltered(meta.CWD, mcp.FromConfigMap(runtimeCfg.MCPServers), mcp.ImportPolicyFrom(runtimeCfg.MCPImport)) // The definition names the servers it uses; everything else the host @@ -285,6 +260,43 @@ func runDaemon(ctx context.Context, args []string) error { } } +// configureRuntimeCompaction leaves Automatic on the conversation's actual route. +func configureRuntimeCompaction( + ag *agent.Agent, + cfg *config.Config, + defaults agentdef.CompactionDefaults, + providers *daemon.ProviderService, +) { + ag.CompactThreshold = defaults.Threshold + if ag.CompactThreshold == 0 { + percent := cfg.CompactPct + if percent == 0 { + percent = config.DefaultCompactPct + } + ag.CompactThreshold = float64(min(max(percent, 10), 90)) / 100 + } + model, provider := defaults.Model, defaults.Provider + if model == "" { + model, provider = cfg.CompactModel, cfg.CompactProvider + } + if model == "" { + return + } + compact, _, err := resolveRuntimeModel(cfg, model, provider, providers) + if err != nil { + ag.CompactFallback = "Custom summarizer unavailable; using this conversation’s model." + config.LogEvent("compaction.fallback", fmt.Sprintf( + "compact model %q (provider %q) unavailable, summaries run on the conversation model: %v", + model, provider, err, + )) + return + } + ag.CompactClient = compact.Client + ag.CompactModel, ag.CompactProvider = compact.Model, compact.Provider + ag.CompactPricing = compact.Pricing + ag.CompactContextLimit, ag.CompactMaxTokens = compact.ContextLimit, compact.MaxTokens +} + // resolveRuntimeModel snapshots the actual endpoint and its catalog rates together. // All model purposes use this resolver so a default provider cannot accidentally // supply another endpoint's price or output limits. diff --git a/cmd/whip/daemon_test.go b/cmd/whip/daemon_test.go index 85151dec2..ddd508c2b 100644 --- a/cmd/whip/daemon_test.go +++ b/cmd/whip/daemon_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/agentdef" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" @@ -359,28 +361,131 @@ func TestResolveRuntimeModelUsesSelectedProviderPricing(t *testing.T) { } } -func TestRuntimeModelDoesNotRouteBuiltinCompactionToAnotherProvider(t *testing.T) { +func TestConfigureRuntimeCompactionAutomaticUsesConversation(t *testing.T) { + for _, name := range []string{"first run", "openai only", "blank with stale provider"} { + t.Run(name, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + cfg := config.Default() + if name != "first run" { + cfg = &config.Config{ + DefaultModel: "host-default", DefaultProvider: "openai", + Providers: map[string]config.Provider{ + "openai": {BaseURL: "https://api.openai.com/v1", APIKey: "fixture"}, + }, + Models: map[string]config.Model{ + "host-default": {Providers: []string{"openai"}}, + }, + } + } + if name == "blank with stale provider" { + cfg.CompactProvider = "missing-provider" + } + client := &llm.Client{BaseURL: "https://conversation.test/v1"} + ag := &agent.Agent{Client: client, Model: "conversation-model", Provider: "conversation-provider"} + configureRuntimeCompaction(ag, cfg, agentdef.CompactionDefaults{}, nil) + if ag.CompactClient != nil || ag.CompactModel != "" || ag.CompactProvider != "" || ag.CompactFallback != "" { + t.Fatalf("automatic mode resolved a separate route: model=%q provider=%q fallback=%q", + ag.CompactModel, ag.CompactProvider, ag.CompactFallback) + } + if ag.Client != client || ag.Model != "conversation-model" || ag.Provider != "conversation-provider" { + t.Fatal("automatic compaction changed the conversation route") + } + if ag.CompactThreshold != 0.5 { + t.Fatalf("automatic threshold = %v, want 0.5", ag.CompactThreshold) + } + }) + } +} + +func TestConfigureRuntimeCompactionCustomRoute(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) - t.Setenv(config.InferenceNetEnvVar, "") - cfg := config.Default() - cfg.DefaultModel, cfg.DefaultProvider = "router-coding", "openrouter" - cfg.Providers["openrouter"] = config.Provider{BaseURL: "https://router.test/v1", APIKey: "fixture"} - cfg.Models["router-coding"] = config.Model{Providers: []string{"openrouter"}, Context: 8192} - if err := config.SaveCatalogs(map[string]config.Catalog{"openrouter": {BaseURL: "https://router.test/v1", Models: []config.ModelInfoLite{{ID: "router-coding"}}}}); err != nil { - t.Fatal(err) - } - main, _, err := resolveRuntimeModel(cfg, "", "") - if err != nil || main.Model != "router-coding" || main.Provider != "openrouter" { - t.Fatalf("main route: %+v, %v", main, err) - } - if _, _, err := resolveRuntimeModel(cfg, cfg.CompactModel, cfg.CompactProvider); err == nil { - t.Fatal("built-in Inference compaction model was routed to OpenRouter; factory must retain main-model fallback") - } - // A deliberately configured auxiliary model on this provider still works. - cfg.CompactModel = "router-coding" - compact, _, err := resolveRuntimeModel(cfg, cfg.CompactModel, cfg.CompactProvider) - if err != nil || compact.Model != main.Model || compact.Provider != main.Provider { - t.Fatalf("configured compaction: %+v, %v", compact, err) + price := llm.Pricing{Prompt: "0.000002", Completion: "0.000004"} + cfg := &config.Config{ + Providers: map[string]config.Provider{"custom": {BaseURL: "https://custom.test/v1", APIKey: "fixture"}}, + Models: map[string]config.Model{ + "summarizer": {ID: "summary-api", Providers: []string{"custom"}}, + "deepseek-v4-flash-0731": {Providers: []string{"custom"}, Context: 16000, MaxOut: 1200}, + }, + CompactModel: "summarizer", CompactProvider: "custom", CompactPct: 65, + } + if err := config.SaveCatalogs(map[string]config.Catalog{ + "custom": {BaseURL: "https://custom.test/v1", Models: []config.ModelInfoLite{ + {ID: "summary-api", ContextLength: 32000, MaxCompletionTokens: 2048, Pricing: price}, + }}, + }); err != nil { + t.Fatal(err) + } + ag := &agent.Agent{} + configureRuntimeCompaction(ag, cfg, agentdef.CompactionDefaults{}, nil) + if ag.CompactClient == nil || ag.CompactModel != "summary-api" || ag.CompactProvider != "custom" { + t.Fatalf("custom route = %q %q", ag.CompactModel, ag.CompactProvider) + } + if ag.CompactContextLimit != 32000 || ag.CompactMaxTokens != 2048 || ag.CompactPricing != price { + t.Fatalf("custom limits/pricing = %d %d %+v", ag.CompactContextLimit, ag.CompactMaxTokens, ag.CompactPricing) + } + if ag.CompactThreshold != 0.65 || ag.CompactFallback != "" { + t.Fatalf("custom settings = %v %q", ag.CompactThreshold, ag.CompactFallback) + } + + // An explicitly stored former default remains a custom model; definitions + // take precedence over host settings without guessing at user intent. + ag = &agent.Agent{} + configureRuntimeCompaction(ag, cfg, agentdef.CompactionDefaults{ + Model: "deepseek-v4-flash-0731", Provider: "custom", Threshold: 0.3, + }, nil) + if ag.CompactModel != "deepseek-v4-flash-0731" || ag.CompactThreshold != 0.3 || ag.CompactMaxTokens != 1200 { + t.Fatalf("definition override = %q %v %d", ag.CompactModel, ag.CompactThreshold, ag.CompactMaxTokens) + } +} + +func TestConfigureRuntimeCompactionMissingCustomFallsBack(t *testing.T) { + for _, name := range []string{"missing route", "missing credentials", "disabled provider"} { + t.Run(name, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("WHIP_TEST_MISSING_COMPACTION_KEY", "") + cfg := &config.Config{ + CompactModel: "deepseek-v4-flash-0731", CompactProvider: "custom", + Providers: map[string]config.Provider{}, Models: map[string]config.Model{}, + } + if name != "missing route" { + cfg.Models[cfg.CompactModel] = config.Model{Providers: []string{"custom"}} + cfg.Providers["custom"] = config.Provider{ + BaseURL: "https://custom.test/v1", APIKeyEnv: "WHIP_TEST_MISSING_COMPACTION_KEY", + } + } + if name == "disabled provider" { + cfg.Providers["custom"] = config.Provider{BaseURL: "https://custom.test/v1", Auth: "none"} + cfg.DisabledProviders = []string{"custom"} + } + ag := &agent.Agent{Model: "conversation-model", Provider: "openai"} + configureRuntimeCompaction(ag, cfg, agentdef.CompactionDefaults{}, nil) + if ag.CompactClient != nil || ag.CompactModel != "" || ag.Model != "conversation-model" || ag.Provider != "openai" { + t.Fatal("unavailable custom route did not retain conversation fallback") + } + if ag.CompactFallback != "Custom summarizer unavailable; using this conversation’s model." { + t.Fatalf("fallback = %q", ag.CompactFallback) + } + }) + } +} + +func TestConfigureRuntimeCompactionClampsLegacyThresholds(t *testing.T) { + for _, test := range []struct { + name string + percent int + want float64 + }{ + {name: "automatic", want: 0.5}, + {name: "legacy low", percent: 5, want: 0.1}, + {name: "legacy high", percent: 95, want: 0.9}, + } { + t.Run(test.name, func(t *testing.T) { + ag := &agent.Agent{} + configureRuntimeCompaction(ag, &config.Config{CompactPct: test.percent}, agentdef.CompactionDefaults{}, nil) + if ag.CompactThreshold != test.want { + t.Fatalf("threshold = %v, want %v", ag.CompactThreshold, test.want) + } + }) } } diff --git a/docs/agent-loop.md b/docs/agent-loop.md index ef4a4d62e..128392645 100644 --- a/docs/agent-loop.md +++ b/docs/agent-loop.md @@ -29,10 +29,19 @@ the complete history or oversized input. `context.inspect/search/read` lets a cell retrieve only relevant spans. This keeps large corpora out of every model request without making them inaccessible. -Proactive compaction runs when estimated context crosses the configured -fraction of the model window. A provider context-limit error may trigger one -reactive compaction and retry. Compaction summaries and raw-history cutoffs -are committed with the root turn. +Proactive compaction runs when the provider-reported prompt usage (or a token +estimate when usage is unavailable) crosses the configured fraction of the +conversation model's window. Automatic uses 50%; custom host thresholds accept +10–90%. A provider context-limit error may trigger one reactive compaction and +retry. Compaction summaries and raw-history cutoffs are committed with the turn. + +The default summarizer is the agent's own conversation model/provider, including +children with a different model. A custom host or definition route may override +it. A missing custom route or insufficient known context capacity falls back to +the conversation route; a definite safe provider rejection can also trigger one +fallback. Uncertain completion, partial output, cancellation, and accounting or +budget failures never trigger a second route. Notices and the summary's trace +make fallback visible. See [compaction settings](models-providers.md#compaction-model). A single provider call failing does not fail the turn. A stream that sends nothing for the stall timeout (120 s on OpenAI-compatible chat streams, 300 s diff --git a/docs/backend-redesign-plan.md b/docs/backend-redesign-plan.md new file mode 100644 index 000000000..477abdd20 --- /dev/null +++ b/docs/backend-redesign-plan.md @@ -0,0 +1,650 @@ +# Whip backend redesign and delivery plan + +Status: proposed; implementation has not started under this plan. +Written: 2026-09-27. Planning reference: `6f02507bf`. + +Build a simpler Go backend with explicit ownership, uniform root/child sessions, +and a matching SDK and client contract. Deliver it in working increments with a +small, continuously green regression suite. + +This document records the intended replacement architecture and its delivery +gates. It does not describe current behavior. Existing engineering guides remain +the references for current implementation; update them as each change lands. +In particular, follow [frontend.md](frontend.md) when changing SDK, +protocol, or application boundaries. Historical plans are context, not additional +requirements for the replacement. + +## Scope and constraints + +- Keep the core backend in Go. TypeScript examples from the design discussion + illustrated concepts; they did not propose moving execution into clients. +- Start with fresh tables, configuration, runtime identity, and a new protocol + major. No old-data importer, old-config reader, dual writes, or old-protocol + compatibility layer is required. +- Preserve wanted product capabilities. Changing their implementation does not + implicitly remove them. Record deliberate feature retirements explicitly. +- Update the TypeScript SDK, shared app, web, desktop, mobile, Go client, CLI, + TUI, ACP bridge, examples, and documentation as applicable. +- Reuse useful provider, engine, transport, UI, and platform implementations + where they fit the new boundaries. Evaluate reuse at the responsibility level. +- Keep SQLite and the existing socket/JSON-RPC/gateway transport approach unless + implementation evidence establishes a concrete reason to change them. +- Develop against disposable homes and databases. The old user data directory + can remain unused; cutover does not require deleting it. + +## Redesign philosophy + +1. **Give every fact one authority.** Database records own durable facts. Live + workers own execution handles. SDK views own reconstructed client state. + Derived caches and projections must identify their source and invalidation. +2. **Use one session model at every depth.** Roots and children share records, + execution, history, and client operations. Parent relationships and explicit + policies explain their differences. +3. **Separate retained state from execution.** A session exists without a live + worker. Reading history does not start work. Loading a worker does not invent + configuration or authority missing from storage. +4. **Make transitions explicit.** Input admission, turn start, model dispatch, + host effects, transcript writes, and completion each have defined durability + and failure semantics. +5. **Keep abstractions small.** Use concrete structs, ordinary constructors, + direct composition, and small consumer-owned interfaces where useful. Avoid + a generic workflow framework, service locator, or repository per table. +6. **Preserve meaningful distinctions.** Inputs, mail, turns, messages, model + attempts, and host operations have different lifetimes. Unifying their + storage envelopes must not erase those semantics. +7. **Allow representations to serve their purpose.** Stored messages, provider + requests, and UI projections can have different shapes. Explicit conversion + is useful; independently mutable copies of the same fact are not. +8. **Bound retained and live resources.** Queues, worker counts, event replay, + content reads, transcript pages, and client caches need explicit limits and + observable exhaustion or truncation behavior. +9. **Make deletion part of delivery.** Remove superseded implementations and + tests as their replacements land. Keep historical reference in Git. + +## Domain ownership and persistence + +The names below establish responsibilities. Exact Go fields and SQL columns are +settled in phase 1 before dependent implementations grow around them. + +| Concept | Owns | Authoritative storage | +| --- | --- | --- | +| AgentDefinition | Immutable revision of defaults, instruction policy, tool descriptions, child templates, hook/output declarations | SQL definition revisions, including built-ins | +| SessionTree | Shared policy and limits; conversation title, archive/pin metadata; common engine selection | SQL | +| Session | Identity, tree/parent relationship, source definition revision, resolved configuration and its revision, working directory, retained lifecycle | SQL | +| Input | Accepted work, recipient, source, queue/delivery state, link to execution | SQL | +| RequestReceipt | Stable request identity, payload identity, admission/outcome needed for client recovery | SQL; provider credentials and ephemeral operations excluded | +| Turn | Execution identity, captured configuration revision, accepted inputs, start/end, durable outcome | SQL | +| Message | Authored/model/tool transcript entry with stable identity, ordering, and content references | SQL; large/binary bodies in content storage | +| Compaction | Summary and exact transcript boundary summarized | SQL | +| ModelContext | Composed instructions, selected summary, recent messages and provisional request data | Derived memory | +| SessionWorker | Loaded REPL, current execution snapshot, cancellation and temporary buffers | Memory | +| Runtime | Scheduler, live worker registry, resource lifetime and coordination | Memory; reconstructs work from SQL | +| ModelAttempt | One provider request, logical-call identity, route/pricing snapshot, outcome, usage and settlement state | SQL | +| Operation | Host-action admission, authority, dispatch, outcome and uncertainty | SQL; live handles remain in memory | +| Budget / Grant | Enforced limits, reservations and scoped authority | SQL; derived totals have explicit owners | +| SessionMail | Inter-session communication and delivery/acknowledgement state | SQL, distinct from execution inputs | +| SessionState / TreeState | Explicit private/shared application state and relevant subscriptions | SQL, distinct from VM globals | +| REPLCheckpoint | Opaque engine image, compatibility metadata, integrity and execution boundary | Durable storage; initially SQL binary payload is acceptable | +| Content | Immutable bytes, metadata and scoped access references | Bodies in blob files; metadata/references/grants in SQL | +| ProviderConfiguration | Host routes, endpoint configuration and credential references | Host config files and secret sources | +| Event / Span | Bounded observation/replay and diagnostic evidence | Durable bounded records where needed; streaming deltas may be transient | +| SDK view | Bounded tree/session snapshots, history windows and live presentation | Reconstructible client memory | +| Client draft / recovery record | Unsubmitted user work and request identity metadata | Explicit device storage; separate from authoritative transcripts | + +### Required ownership rules + +- Exactly one root exists per tree. Other sessions have a parent in the same + tree; relationships cannot form cycles. Root lookup is derived from this + relationship rather than an independently writable second identity. +- Every session uses the same transcript table and turn lifecycle. There is at + most one active turn per session, enforced through runtime ownership and a + database constraint or transactional claim. +- Creating a session resolves a pinned definition plus explicit overrides, + validates the result, deeply copies maps/slices, and persists effective config. + Editing a definition or host default does not silently modify that session. +- Configuration changes are explicit and revisioned. A running turn uses its + captured configuration; changes take effect at a defined safe boundary. +- Model changes preserve history, children, REPL state, and unrelated integration + resources. Model selection contains no provider client or credentials. +- Prompt policy belongs to configuration. Dynamic project files, skills, and + other declared context sources are refreshed at documented boundaries. Keep + audit evidence of the actual composed request where required; do not pretend + a pinned definition freezes external files. +- Definitions advertise available operations. Grants, permission decisions and + host policy determine actual authority. Child creation cannot widen authority + or evade ancestor budget limits. +- A SessionWorker may cache immutable configuration and derived context. The + database remains authoritative; there is one path for committed updates to + invalidate or replace those execution snapshots. +- SessionTree starts as data and policy. One runtime scheduler and per-session + execution ownership are the default. Add another actor only for an invariant + that transactions and the scheduler cannot express clearly. +- Client disconnect, view closure, and aborted local waits release observation. + Cancellation of accepted execution is an explicit operation targeting a turn. +- Parent-turn completion does not implicitly delete a retained child. Stop, + cancel, session deletion, subtree deletion and worker eviction have distinct + semantics and resource cleanup. +- VM state, explicit session state, shared tree state, and conversation history + remain separate. Live process, browser, terminal and executor handles cannot + be reconstructed merely by restoring their IDs. +- A content digest identifies bytes; an authorized reference grants scoped + access. Provider encoding can hydrate bytes without rewriting the stored + transcript into base64 bodies. +- Store model accounting once per actual attempt, including retries and helper + calls. Preserve unknown usage/cost separately from known zero. Budget counters + are transactional projections, with used/reserved/uncertain distinguished. +- Events provide bounded recovery and observation. Canonical state and final + outcomes cannot depend on replaying an indefinitely retained event log. + +### Fresh schema direction + +| Current organization | Replacement direction | +| --- | --- | +| Root `sessions` plus `agents` | `session_trees` plus uniform `sessions` | +| `messages` plus child `transcript_messages` | One `messages` table keyed by session | +| Separate root/child turn commit paths | One `turns` lifecycle and persistence API | +| Special built-in definition resolution | Revisioned definition documents for every template | +| Configuration reconstructed through several owners | Stored effective session config plus explicit revisions | +| Model-call ledger plus competing usage representations | Attempt ledger with explicit budget/read projections | +| Checkpoints plus legacy scratch restoration | One checkpoint contract with engine-specific payloads | + +This is a responsibility mapping, not an ALTER TABLE migration. Start with a +fresh schema version. Retain normal schema versioning for future releases of the +new system; omit migrations from the retired implementation. + +## Go boundaries and execution flow + +Target core packages: + +```text +cmd/whip/ Startup, explicit dependency construction, CLI entry points +internal/session/ Durable conversation values and validation +internal/store/ SQLite schema, queries, atomic transitions, recovery +internal/runtime/ Scheduling, workers, cancellation, coordination +internal/runner/ Model/code/tool loop and model-context assembly +internal/model/ Provider implementations and request/response conversion +internal/engine/ QuickJS/Starlark execution and checkpoint formats +internal/tool/ Dispatch and integration with scoped authority checks +internal/content/ Immutable content bodies and bounded access +internal/config/ Host configuration and credential resolution +internal/protocol/ Wire DTOs, operation/event declarations, generation metadata +internal/rpc/ Wire validation and application-operation mapping +internal/client/ Go client for CLI, TUI and ACP +``` + +Keep existing integration packages where useful. This is a boundary map, not a +requirement to create empty packages or move every leaf implementation. + +Domain values must not import SQLite, runtime, provider clients, or engines. +Store owns transactions and no live process managers. Runner uses narrow injected +interfaces and cannot reach a global runtime or issue SQL. Protocol owns explicit +wire shapes rather than exporting persistence implementations. Both clients +depend on the wire contract without importing backend execution packages. + +Keep transactions intact across related tables. Splitting persistence into many +small repositories must not force orchestration to simulate database atomicity. +Long provider calls and host effects run outside database transactions and +scheduler locks. Root and child execution follow the same path: + +```text +client / schedule / authorized agent + -> admit work and commit request receipt + input + -> scheduler claims input and starts a turn + -> worker captures config and builds model context + -> runner dispatches recorded model attempts and authorized host operations + -> completed messages / cells become durable + -> turn outcome and related input transitions commit + -> clients reconcile committed state with live presentation +``` + +## Durability and recovery contract + +Define these transitions before adding more features to the runner: + +| Boundary | Required guarantee | +| --- | --- | +| Input admission | Retry identity, payload identity and input admission commit atomically; same identity with different payload is rejected | +| Turn start | Claim eligible input, link it to the turn, capture config and enforce one active turn atomically | +| Model dispatch | Record attempt/reservation before dispatch; settle each actual attempt without treating unknown cost as zero | +| Host effect | Validate authority, persist admission and record dispatch/outcome; uncertain effects are not automatically repeated | +| Transcript append | Completed entries have stable IDs/order and survive restart; streaming fragments are explicitly provisional | +| Cell checkpoint | Checkpoint identifies engine compatibility and the completed cell/transcript boundary it covers | +| Turn finish | Final outcome and associated input/receipt transitions commit together where they form one invariant | +| Observation | Notify after committed state exists; snapshot/replay closes notification gaps | + +Persist completed transcript entries during a running turn. On a crash, retain a +truthful partial conversation associated with an interrupted turn. At cell +boundaries, commit checkpoint metadata/image and transcript evidence together +when their consistency requires it. External effects cannot be rolled back by +that transaction; their independent operation records remain necessary. + +Recovery preserves unclaimed queued work, identifies interrupted turns, and +retains unresolved dispatch/accounting outcomes. Retrying failed persistence +must not reissue the provider request or host effect. A retry policy must identify +which work can safely be retried and when explicit input is required. + +Blob writes need an explicit ordering with reference commits and orphan cleanup. +Checkpoint incompatibility/corruption needs an explicit failure/reset policy; +never silently replay code to rebuild state containing external effects. + +## SDK and client contract + +Keep the Go-derived wire generation path. Generate TypeScript declarations, +schemas, operation metadata and validators from the protocol registry. Treat +generated drift and actual Go/TypeScript interchange as required checks. + +The client-facing shape should make identity consistent: + +| Concern | Intended service shape | +| --- | --- | +| New conversation tree | `trees.create(...)`, returning tree and root session identities | +| Shared metadata/policy | `trees.get/update(...)` | +| Any root or child | `sessions.get(id)` / `session(id)` | +| Child creation | `sessions.spawn({ parentId, ... })` | +| Work submission | `session.submit(...)`, returning accepted input identity | +| History | `session.history(...)` | +| Execution inspection/cancellation | `turns.get/cancel(...)` | +| Descendants | `sessions.list({ treeId, parentId })` | +| Templates | `definitions.register/get/list(...)` | + +A convenience `run()` may follow an input into its associated turn. Admission, +execution outcome, and the lifetime of a local stream remain distinguishable. +Durable requests retain stable recovery identities. Queries and ephemeral +operations such as terminal input do not enter an automatic replay queue. + +Use lightweight tree views and uniform session transcript views. The SDK owns +bounded snapshots, event reconciliation, reconnect and request recovery. The app +owns selection, drafts and presentation, with no second reducer for daemon truth. +Snapshot revisions/cursors must provide a gap-free handoff to updates; expired +replay cursors require a fresh snapshot. Large counters remain exact across Go +and JavaScript. Content references remain scoped and lazy. + +Custom tool/hook schemas belong to definition revisions. Executable handlers and +their connection-bound availability belong to live executor bindings. Reconnect +must not recreate authority or replay arbitrary effects. + +Porting includes shared React presentation, web/gateway transfers, desktop native +bridges and packaging, mobile suspension and local recovery, Go CLI/TUI, ACP, +examples, fixtures and user documentation. SDK work begins with the first working +slice; client adoption continues through the project rather than waiting for a +completed backend. + +## Development, testing and CI process + +### Working loop + +1. State one behavior or invariant to deliver, including the important failure. +2. Add the smallest meaningful check that would catch it breaking. +3. Implement the path through the required layers. +4. Run affected tests while editing; run the active change gate when complete. +5. Review state ownership, transaction boundaries and cleanup; delete superseded + code/tests and commit a coherent increment. +6. Update phase evidence and feature/test disposition only where they changed. + +Use an isolated integration branch and disposable runtime storage. Preserve a +baseline commit and record its actual check results before replacement work. +Use small reviewable changes without requiring every intermediate increment to +support the retired application. Each active target must remain buildable and +green. Retained integration code must not conceal an import back into the retired +orchestration. + +Do not create tests for trivial forwarding or field assignments solely to raise +coverage. Prioritize transitions, transactions, concurrency, authority, recovery, +and provider/wire conversion. Test an invariant at the lowest layer that proves +it, then add cross-layer coverage where crossing the boundary is itself risky. + +### Feedback gates + +The following commands are proposed work for phase 0, not existing commands or +measured performance claims. Use the current Taskfile and existing test tools. + +| Gate | When and scope | Warm feedback target | +| --- | --- | --- | +| Focused checks | During edits: affected package tests and typechecking | A few seconds | +| `check:fast` | Before commit: formatting and compact active core regression suite | Under one minute | +| `check:change` | Before integration merge: active backend tests/build/vet, targeted race checks, affected SDK/client tests, contract drift/interoperability | A few minutes | +| `check:phase` | Phase completion: full active acceptance, broader race/platform/client checks, packaging where introduced | Deliberate longer run | + +Keep pre-commit hooks lightweight. Avoid automatically rebuilding every client +or running the full cross-platform suite for each local checkpoint. Measure gate +duration and fix costly setup before adding a test-selection framework. + +Maintain a short explicit active-target list in the task configuration. Include +new packages as they land, along with affected retained dependencies. Shared +domain/protocol changes trigger all active consumers, not only changed files. +Not-yet-ported targets have an assigned phase; they do not create permanent +expected-red jobs. Every supported target must return to the gate by cutover. + +Configure CI triggers and required status checks for the integration branch. +Required jobs must actually run and their failures must reach the aggregate gate. +Keep production branch policy intact while the replacement has a narrower active +scope. Remove the rewrite branch's global 90% coverage floor as a blocking gate; +keep coverage reports diagnostic and require explicit high-risk scenario coverage. + +Run deterministic tests without live provider credentials. Broader OS/browser +matrices, installation, signing, fuzzing, performance measurements and live-model +evaluation run at relevant milestones. A failure in a supported capability remains +a regression even when detected by the broader gate. Live-model quality evaluation +is separate from deterministic runtime correctness. + +### Existing test disposition + +Classify by feature/test family as its subsystem is touched: + +| Category | Action | +| --- | --- | +| Required behavior with retained implementation | Keep; adapt setup only as necessary | +| Required behavior with replacement implementation | Rewrite against its new public boundary; preserve valuable failure scenarios | +| Intentionally removed behavior | Delete with the old implementation | +| Capability scheduled for a later phase | Record the obligation and target phase; cover it before declaring the feature supported | + +Historical bug tests are requirements evidence. Actor names, duplicate table +layouts, old wire fields and obsolete migration paths are not automatically new +requirements. Replacing an assertion requires identifying whether the behavior +changed, the implementation broke, or the test was coupled to obsolete structure. +Do not simply update expectations until a failure disappears. + +Keep the old suite in baseline Git history. Avoid an archived test directory, +permanent skip lists, blanket retries, and compatibility shims built just to keep +old assertions alive. `go test -run` still compiles all tests in selected packages; +remove or port obsolete tests that no longer compile. + +Maintain one compact table here as families are addressed: + +| Feature/test family | Guarantee retained or retirement decision | Replacement evidence | Target phase / status | +| --- | --- | --- | --- | +| Admission and client recovery | Stable request identity; accepted work survives lost acknowledgement | Pending | 2 | +| Execution and crash recovery | Explicit interruption, durable completed evidence, no uncertain-effect replay | Pending | 3 | +| Accounting | Every dispatched attempt recorded; settlement retry does not redispatch | Pending | 3 | +| Recursion and authority | Uniform session behavior, scoped grants, shared limits | Pending | 4 | +| Context and checkpointing | Raw history retained; checkpoint boundary and fidelity explicit | Pending | 3 and 5 | +| Integrations and product features | Preserve capability outcomes; inspect existing regression scenarios | Pending | 5 | +| All client surfaces | Correct submission, observation, recovery and resource cleanup | Pending | 2 through 6 | +| Old schemas/protocol/scratch compatibility | Retired by fresh-start scope | Delete with corresponding implementation | 1 through 7 | + +### Test fixture and diagnostics + +Adapt existing fixture utilities where useful. Use real temporary SQLite, the +real runtime/protocol/SDK, a scripted provider, and controlled external tools. +Runtime acceptance must execute the real runner; mocking it bypasses the very +orchestration being tested. Keep a small real-provider/real-engine smoke path +separate from the deterministic daily gate. + +Add controls only when a scenario needs them: barriers for dispatch/completion, +provider/tool failures, dropped acknowledgements, disconnection, storage failure, +and daemon restart. Prefer explicit signals and controlled clocks to arbitrary +sleeps. Use a few subprocess kills to establish crash recovery; graceful shutdown +alone is insufficient. Bound every wait and clean up processes and resources. + +Retain useful failure artifacts: database, logs, event trace, scripted actions, +and the command/seed needed to reproduce the failure. A narrow failed commit +must prove rollback or recovery, not merely that a returned error is non-nil. + +Use the same disposable fixture for manual development of permission waits, +children, interruptions and large output. It must not target a developer's normal +daemon or depend on spending model tokens. + +Add a few package-boundary checks for forbidden domain/runtime, store/resource, +and client/execution imports. Keep them tied to intentional dependency rules, +not source-text snapshots or incidental function names. + +## Delivery phases + +Phases are dependency gates. SDK/client work begins in phase 2 and continues +through phases 3–5; phase 6 completes coverage rather than starting client work. +Within a phase, deliver one useful behavior at a time. Only mark a criterion +complete with a passing check or recorded manual evidence. + +| Phase | Deliverable | Depends on | Status | +| --- | --- | --- | --- | +| 0 | Baseline, feedback gates and fixture foundation | None | Pending | +| 1 | Domain contract, ownership, fresh storage/config | 0 | Pending | +| 2 | Working database → runtime → protocol → SDK slice | 1 | Pending | +| 3 | One provider, one engine, execution and recovery | 2 | Pending | +| 4 | Recursion and shared coordination | 3 | Pending | +| 5 | Remaining engines, integrations and product behavior | 4 | Pending | +| 6 | Complete client adoption and product validation | Starts at 2; finishes after 5 | Pending | +| 7 | Cutover, deletion and release readiness | All prior gates | Pending | + +### Phase 0 — Establish the feedback loop + +Record baseline revision/results and set up the integration branch, isolated +storage, active-target gates and fixture lifecycle. Inventory required behavior +families using existing tests and the feature map. Prepare the first admission +and restart scenarios; do not add failing placeholders to the required suite. + +Acceptance: + +- [ ] Baseline identity and actual check results are recorded, including any + pre-existing failures. No unrun check is described as passing. +- [ ] Active targets and the initial behavior/test inventory are explicit. +- [ ] Fast/change/phase tasks run locally; CI runs on integration-branch PRs and + fails visibly when a required check is deliberately broken. +- [ ] Hook behavior is lightweight; broader validation is available explicitly. +- [ ] Fixture startup/shutdown is repeatable in disposable storage, with bounded + waits and failure artifacts. It does not touch the normal runtime. +- [ ] Feedback times are measured once; targets are adjusted transparently if + necessary without silently dropping important checks. + +### Phase 1 — Define the domain and fresh persistence + +Implement durable value types, validation, definition revisions, effective config +resolution, host config and fresh schema. Establish transaction APIs and the +state machines that later code will use. Write the initial wire shapes and +generation fixtures. Choose the first provider and engine for phase 3. + +Acceptance: + +- [ ] Fresh storage/config initializes deterministically with a new identity and + no dependency on legacy readers or migrations. +- [ ] Root uniqueness, parent/tree consistency, cycle prevention and active-turn + uniqueness have meaningful validation/constraint tests. +- [ ] Root and child use the same records, transcript source and persistence API. +- [ ] Built-ins and registered definitions have pinned revisions; resolving and + changing one session cannot mutate another through aliased maps/slices. +- [ ] Each durable field has one authority; configuration update/capture rules + are explicit. Secrets and live resource handles stay outside session rows. +- [ ] Transaction tests cover atomic admission/claims and rollback using real + SQLite. Store construction does not create process/workspace managers. +- [ ] Admission, retry, interruption, cancellation and deletion semantics are + documented sufficiently to implement phases 2–4 without guessing. + +### Phase 2 — Deliver the first working slice + +Connect tree/session creation, accepted input, a scripted model turn, transcript +persistence, outcome, history and observation through the actual runtime and +generated wire contract. Implement a minimal SDK example and initial Go client. +Use the real runner with a scripted provider as soon as the loop exists. + +Acceptance: + +- [ ] An SDK example creates a tree/session, submits work, observes a turn and + reads its durable messages and outcome. +- [ ] Losing an acknowledgement and resubmitting the same identity returns the + same admission; conflicting payload reuse is rejected. +- [ ] Concurrent submissions cannot start two active turns for one session. +- [ ] Reconnect reconstructs completed state without duplicate messages. +- [ ] Unclaimed queued input survives restart; reading history starts no work. +- [ ] Client disconnect/local wait cancellation does not cancel accepted work. +- [ ] Generated declarations/validators and actual Go-to-TypeScript fixtures + agree; the new SDK talks directly to the new contract. +- [ ] This end-to-end slice is part of the required change gate. + +### Phase 3 — Make execution and recovery trustworthy + +Add one real provider and one engine, content references, explicit operation +authority, permission interaction, model-attempt accounting, cancellation and +checkpointing. Establish failure behavior before broadening integrations. + +Acceptance: + +- [ ] The real runner executes model/code/tool work through injected boundaries. + A scripted provider exercises the same loop as the real provider. +- [ ] Every dispatched model request, including retries/helpers, has an attempt + record and truthful usage/cost/uncertainty; settlement failure cannot cause + an automatic second provider dispatch. +- [ ] Tool effects require scoped authority and have durable operation evidence. + Denial/revocation prevents the relevant effect; unresolved effects are not + blindly replayed after restart. +- [ ] Completed messages survive a crash mid-turn; provisional output reconciles + without becoming a second committed message. +- [ ] Checkpoint integrity, compatibility, execution boundary and failure policy + are tested; restoration does not replay external effects. +- [ ] Injected transaction failures and selected real process kills yield the + documented queued/interrupted/uncertain outcomes. +- [ ] Explicit cancellation, deadlines and resource cleanup pass targeted race + and lifecycle tests. Cancellation remains serviceable during slow calls. +- [ ] A model/config change takes effect at its documented boundary while + preserving REPL, history and unrelated resource state. +- [ ] Content is authorized and bounded; provider encoding leaves durable + references intact. One real-provider/engine smoke has recorded evidence. + +### Phase 4 — Add recursion through the same execution path + +Implement child admission, scheduling, authority/budget narrowing, mail, +session/tree state, retry/report policies, and subtree lifecycle operations. + +Acceptance: + +- [ ] Child creation atomically persists identity/config/authority and its + initial input before scheduling; restart retains accepted child work. +- [ ] Root and child pass the same applicable turn, history, cancel and recovery + scenarios. No parallel child commit or transcript implementation exists. +- [ ] Concurrent descendants cannot overspend shared reservations or widen + authority. Unrelated sessions cannot alter each other's scoped state. +- [ ] Saturated worker/kernel capacity still permits required child progress; + parent waits do not deadlock children. Queued work remains durable. +- [ ] Retry and report behavior is explicit policy; failed/uncertain work follows + the selected retry semantics at every depth. +- [ ] Mail delivery/acknowledgement is distinct from human inspection and input + admission. Private and shared state isolation is tested. +- [ ] Parent-turn completion, child cancellationch, subtree deletion and worker + eviction release the intended resources without implicit data loss. + +### Phase 5 — Port retained product capabilities + +Port the remaining engine/provider implementations, compaction, goals, schedules, +fork/rewind/workspace snapshots, MCP, browser/computer, terminals, custom tools, +hooks and output validation. Consult the feature map and existing regression +tests for capabilities omitted from this initial list. Retain the native helper +and host/gateway trust boundaries while replacing their orchestration callers. + +Acceptance: + +- [ ] Each retained capability is implemented, or its explicit retirement is + recorded. No feature disappears merely because its old tests were deleted. +- [ ] Both engines pass common contract tests and their documented checkpoint + fidelity/compatibility tests; shared semantics do not depend on language. +- [ ] Compaction preserves raw transcript history and records exact boundaries. + Fork/rewind defines conversation, checkpoint and external workspace effects + and prevents stale client history from being silently applied. +- [ ] Goals/schedules admit ordinary inputs; due work is handled according to + policy even when its session worker is not already loaded. +- [ ] Integration reloads/model changes preserve unrelated children, grants, + REPL and resource ownership. +- [ ] Executor disconnect, required/optional hooks, tool schemas and output + validation have explicit failure behavior and matching SDK coverage. +- [ ] Human terminal/browser resources and agent authority remain distinct; + reconnect does not silently restore revoked attachments or replay effects. +- [ ] All retained feature families have replacement evidence and use the new + core; no compatibility wrapper delegates execution to the retired runtime. + +### Phase 6 — Complete SDK and client adoption + +Finish the uniform services and views, shared app, web gateway, desktop native +bridges, mobile, Go client, CLI/TUI and ACP. Update examples and canonical docs. +Preserve app-owned drafts, selection and reading behavior without duplicating +daemon state in a second client store. + +Acceptance: + +- [ ] Every supported client builds against the new generated contract and + exercises submission, observation and explicit cancellation. +- [ ] Uniform session handles/history/views work for roots and children. SDK + recovery distinguishes acceptance, outcome and local observation errors. +- [ ] Snapshot/subscription handoff, dropped events, expired replay, restart and + lost acknowledgement recover without duplicate work or presentation. +- [ ] Large histories/content and slow consumers remain bounded and report + truncation/unavailability truthfully; cross-session access is rejected. +- [ ] Desktop native bindings, mobile suspension/resume, web content transfer, + Go client and ACP pass their relevant transport/lifecycle checks. +- [ ] Fresh namespaces for local recovery records/caches prevent old identities + from targeting the new runtime. Unsupported peers fail initialization. +- [ ] Manual product checks cover interrupted work, permissions/questions, + children, content, drafts and navigation on the affected surfaces. +- [ ] Examples, SDK docs and canonical frontend/protocol guides describe shipped + behavior. All supported client targets are now in required CI. + +### Phase 7 — Cut over and remove the retired core + +Finish deletion, restore comprehensive product gates and prepare matching +backend/SDK/client artifacts with a fresh runtime/config namespace. + +Acceptance: + +- [ ] Old root/child orchestration, duplicate transcript paths, legacy migrations, + scratch readers, protocol shapes and superseded reducers/tests are removed. +- [ ] No active target depends on retired execution code or compatibility + aliases. Temporary exclusions and scaffolding have been removed. +- [ ] All retained guarantees have replacement coverage; the disposition table + contains no unresolved obligations for supported features. +- [ ] Full applicable build, vet/lint, race, contract, SDK, client, platform and + packaging gates pass on the final revision, with exact coverage recorded. +- [ ] Fresh installation/startup and restart are validated on shipped targets; + incompatible clients fail clearly. Matching artifacts use one source + revision and verified shared renderer where applicable. +- [ ] Representative real-provider/engine workflows and bounded-resource checks + have evidence. Unverified platform/manual checks remain explicitly named. +- [ ] Release/setup docs explain fresh config/data and retain old directories + without silently importing or deleting them. +- [ ] The normal supported-product gate replaces the temporary active-target + scope; this plan records completion and links to canonical documentation. + +## Decisions to settle before dependent work + +These are concrete decisions, not permission gates for routine implementation. +Resolve them with the simplest behavior consistent with the ownership rules and +record the result here. A phase cannot pass while its required semantics remain +undecided. + +| Decision | Latest point | Starting position | +| --- | --- | --- | +| Submit vs steer, input batching, input-to-turn mapping | Phase 1 | Queued admission is durable; steering targets an explicit active turn | +| Configuration updates while busy | Phase 1 | Revisioned changes affect the next turn; current execution snapshot stays fixed | +| Session stop, cancellation, deletion and subtree policy | Phase 1 | Separate operations with explicit descendant/resource effects | +| First provider and engine | Phase 1 | Choose retained implementations with useful deterministic fixtures | +| Retry policy after interruption or uncertain dispatch | Before phase 3 effects | Preserve uncertainty; no automatic replay of unknown external effects | +| Cell/checkpoint/transcript commit boundary and fidelity | Before phase 3 checkpointing | Completed entries persist during turns; checkpoint names its covered boundary | +| Question/permission lifetime across crash | Phase 3 | Persist decisions as appropriate; never claim a lost live waiter resumed | +| Provider config changes and request provenance | Phase 3 | Host credentials remain live; record the actual request route/pricing snapshot | +| Fork/rewind relationship to VM and workspace state | Before phase 5 implementation | Explicit history revision and documented external-state behavior | +| Exact service names, DTOs, cursors and protocol major | Initial subset in phase 1; final before phase 6 completion | One Go-owned wire registry, uniform session identities | +| Feature retirement discovered during porting | Before deleting its only coverage | Preserve by default; record any intentional scope change | + +## Evidence and ongoing maintenance + +For each phase completion, append a brief entry with revision, commands and +results, relevant manual checks, remaining limitations, and links to replacement +tests/artifacts. Keep implementation detail in code and canonical guides; this +file owns the migration sequence, unresolved decisions and acceptance status. + +No implementation or runtime validation is claimed by this planning document. + +Useful starting references: + +- [Current architecture](architecture.md), + [runtime](rlm-runtime.md), + [concurrency](concurrency.md), and + [feature map](features.md). +- [Frontend ownership and validation](frontend.md), + [SDK API](../packages/sdk/README.md), and + [Go contract generator](../cmd/whip-contract/main.go). +- [Current task gates](../Taskfile.yaml), + [CI workflow](../.github/workflows/ci.yml), and + [pre-commit hook](../scripts/git-hooks/pre-commit). +- [Current root-bound SDK](../packages/sdk/src/session.ts), + [Go client in daemon](../internal/daemon/root_client.go), and + [SDK process-restart fixture](../internal/daemon/v2_sdk_test.go). +- [Accounting failure regressions](../internal/daemon/budget_test.go), + [engine recovery tests](../internal/daemon/execution_engine_test.go), and + [compaction regressions](../internal/daemon/manual_compaction_test.go). diff --git a/docs/features.md b/docs/features.md index 79f92bfc3..e20d6b793 100644 --- a/docs/features.md +++ b/docs/features.md @@ -137,6 +137,18 @@ Available modules are summarized in [tools.md](tools.md). bounded summary. - `context.inspect/search/read` returns source metadata and byte spans. - Proactive and reactive compaction protect the provider context window. + Automatic uses each agent's conversation model/provider, with no auxiliary + account requirement. An omitted model and zero threshold mean Automatic (50%); + existing saved custom routes are preserved. Host settings and the idle-session + inspector reuse the catalog model/provider picker; custom thresholds accept + 10–90%. Missing or too-small custom routes and definite safe request rejections + can fall back to the conversation route, with a notice and the actual route and + reason on the summary's trace. Cancellation, uncertain completion, partial + output and accounting/budget failures never cause a second-route replay. + See [compaction settings](models-providers.md#compaction-model), + `cmd/whip/daemon.go`, `internal/agent/agent.go`, + `packages/app/src/settings/configuration.tsx`, and their configuration, + compaction-fallback and settings regression tests. - Large values are immutable, content-addressed, and separately authorized. The deterministic evaluation expands a corpus above 500 KB and proves the @@ -633,8 +645,9 @@ verified tools, helpers, a child, images, title/compaction and restart recovery. later execution failure does not undo naming of an already accepted message. - Deterministic titles shorter than 20 Unicode characters are kept without an LLM call. At 20 characters or more, automatic naming is enabled by default: one - daemon-owned background request uses the compact-model route (or its existing - main-model fallback), using only the user text, with a 20-second timeout. + daemon-owned background request uses the automatic conversation route or saved + custom compaction route (with its setup fallback), using only the user text, + with a 20-second timeout. Definition `surface.auto_title=false` skips this request but retains the deterministic title. No separate per-session enablement command or inspector control is required. @@ -815,6 +828,7 @@ behavior to its owning code and repeatable validation. | Root/child conversations, grouped tool calls, read-only Starlark, bounded history and recipient-scoped drafts | `packages/app/src/{conversation,timeline,composer}.tsx`, SDK session views | `packages/app/test/{timeline,composer}.test.tsx`, production browser fixture; `apps/web/scripts/performance.mjs` exercises 10,000 root messages, 100 retained children, stable selection/scroll and 32 drafts under 16 concurrent streams | | Compact growing composer, shared model/reasoning picker for idle root sessions, and neutral input focus borders | `packages/app/src/{composer,model-selection}.tsx`, shared UI form styles | Composer tests; `apps/web/scripts/browser.mjs` (growth/shrink, explicit model/effort changes, busy state, draft/reload preservation); `apps/web/scripts/model-picker.mjs` (detail-card bounds, side flipping, scrolling, keyboard and resize in Chromium/Firefox); split workspace browser fixture | | Right-aligned user bubbles, hover/focus timestamps and controls, immediate submission previews, queued/running inbox messages | `packages/app/src/{input-presentation,runtime}.ts`, `packages/app/src/{conversation,timeline,composer}.tsx` | `packages/app/test/input-presentation.test.tsx`, composer/runtime tests, `apps/web/scripts/user-messages.mjs` (Chromium/Firefox delayed request, running turn, reload, duplicate text, hover/focus and responsive themes) | +| One completed-agent-response footer with recorded local time, bounded Markdown copy, and root-only Fork from here / Rewind to here actions that keep the selected response | `packages/app/src/{conversation-rows,chat-activity-rows}.ts`, `{timeline,conversation}.tsx`; `internal/agent/agent.go`, `internal/llm/openai.go` | App response grouping/timeline/history-action tests; agent timestamp/provider-filtering and daemon endpoint tests; `apps/web/scripts/user-messages.mjs` (Chromium/Firefox date, clipboard failure/retry, keyboard/touch, themes, inclusive fork/rewind and reload) | | Errors owned by application, host, session, turn, execution, submission, resource, action or validation, each with one canonical display | [Ownership rules](frontend.md#error-ownership-and-canonical-displays), `packages/app/src/error-feedback.tsx`; latest turn outcome only, recorded execution failures retained | `local-errors.test.tsx`, `welcome-recovery.test.tsx`, error ownership browser fixture | | Questions, permission decisions, remembered rules and exact-turn cancellation | `packages/app/src/{requests,conversation}.tsx`, SDK permission/command helpers | `packages/app/test/requests.test.tsx`, two-client production browser fixture, existing daemon permission tests | | Recursive work, mailbox/evidence inspection, goals, schedules, budgets, context and integrations | `packages/app/src/inspector.tsx`, `packages/app/src/details/`, host read services | `packages/app/test/inspector.test.tsx`, `internal/daemon/host_test.go`, generated SDK operation coverage | @@ -1247,8 +1261,12 @@ WHIP's themes. It groups the loaded SDK catalog by exact directory, keeps worktrees distinct, preserves pin/recency order, and shows seven sessions per folder by default. More reveals seven additional loaded sessions at a time; once all are visible, Less resets the folder to seven. It offers New session, Search -sessions and Settings. Hosts have separate headings and connection status within -one sidebar. Directory + preselects its source host and folder in the Local/Remote +sessions and Settings. Local and remote directories interleave by their newest +loaded session update in one virtualized Projects list, with no host headings. +Project headings are text-only. Remote directories show a host name and connection +status, with compact identity/path details and left-aligned server actions. Exact runtime/path keys isolate collapse, scroll, +activity and actions; transient disconnects retain stale rows, explicit detach +clears them. Host-labelled pagination keeps independent catalog limits. Directory + preselects its source host and folder in the Local/Remote creation form; it does not create work until submitted. Search opens a centered dialog with host labels/filter, recent sessions, debounced host search, independent bounded paging, partial errors and arrow/Enter navigation (`session-search-dialog.tsx`; `apps/web/scripts/session-search.mjs`). @@ -1268,7 +1286,7 @@ Code: `packages/app/src/session-sidebar.tsx`, `sidebar-state.ts`, `sidebar-layout.tsx`, `welcome.tsx`, and `session-tab-routing.ts`. Tests: `sidebar-state.test.ts`, `sidebar-layout.test.tsx`, `sidebar-creation.test.tsx`, `session-tab-routing.test.ts`, and the isolated -production-browser workflow `apps/web/scripts/sidebar.mjs`. +production-browser workflows `apps/web/scripts/sidebar.mjs` and `directory-sidebar.mjs`. ## Multiple execution hosts in the web workspace diff --git a/docs/frontend.md b/docs/frontend.md index cf8209fdb..706f9ab01 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1296,6 +1296,17 @@ Provider onboarding, tokens, machine keys, and shared configuration writes remai host-owned. API-key entry is an ephemeral UI input: never place it in drafts, Query persistence, command-recovery storage, or logs. Configuration updates use revision checks; display conflicts instead of overwriting newer settings. + +Compaction settings are automatic-first. An empty summary model means each +conversation uses its own model/provider; zero threshold means Automatic (50%), +not disabled. Existing saved model overrides remain custom. Show the effective +threshold in the summary rows and put overrides in the shared Collapsible. Custom +summary selection reuses CatalogModelPicker so model/provider are one choice, not +independent text inputs; custom thresholds use 10–90%. The host settings and idle +session inspector share this selection contract and preserve revision-checked +drafts. They describe saved defaults, not a live effective route. Actual summary +model/provider and any compaction fallback are read from the existing call trace; +do not add a second client routing resolver or history store. `settings/provider-connections.tsx` reads the inexpensive `provider.list` inventory, scoped to the execution host, independently of model discovery. Opening setup and explicit Settings Refresh use the ephemeral `provider.discover` @@ -1566,7 +1577,11 @@ execution also hosts the agent editor (`settings/agents.tsx`): it lists the host's definitions from `definitions.list`, derives the module and capability catalog from the built-in coding definition, builds the canonical document with the SDK's `defineAgent`, and registers it; registering an existing id adds a -revision and never changes running sessions. The welcome page's Agent picker +revision and never changes running sessions. Creation, copying and editing use +the same compact dialog: stacked UI Fields, responsive module/capability Fieldsets, +and a More options disclosure for project discovery and session flags. Keep +authority choices visible; do not reuse the full-page SettingsRow layout inside +this form. The welcome page's Agent picker reads the same query (`definitions.ts`) and sends `definition` with `session.create`; hosts that do not advertise the registry hide the picker. Every category uses the Settings heading and shared groups; no category shows the Attention @@ -1740,9 +1755,12 @@ adds no live region, requests, retained history, or SDK event reconciliation. changes are coalesced to at most 30 parses/second, with stable unchanged block ASTs and a 512-document / 2 MiB source cache. This is not an incremental parser. Conservative trailing inline delimiter completion affects display only. One -response-copy footer uses original retained assistant prose before display splits; -reasoning, tool output and mailbox deliveries are excluded. Partial history reads -say **Copy visible response**, with the existing 256K-character bound. Selected +response footer uses original retained assistant prose before display splits for +copying; reasoning, tool output and mailbox deliveries are excluded. Partial +history reads say **Copy visible response**, with the existing 256K-character +bound. The same projection owns its last assistant timestamp and committed +history endpoint; folded tool-result sequences remain part of that endpoint. +Unknown or incomplete endpoints do not expose history mutations. Selected Markdown blocks preserve their DOM until selection ends, then display the latest source; other blocks continue streaming. Code decoration receives original token offsets and never changes its source or copy semantics. @@ -1959,8 +1977,22 @@ User messages use right-aligned, theme-derived bubbles. Timestamps and existing copy/history actions appear below the bubble on hover or keyboard focus; touch keeps the controls available. Show recorded `sent_at` values when supplied, and never invent timestamps for historical messages that lack them. -Agent responses omit a repeated author heading and show one left-aligned copy -control in the completed response footer, with no per-paragraph copy control. +Agent responses omit a repeated author heading and show one left-aligned +history-menu/copy/time footer per completed response, mirroring the user footer, +not per paragraph or tool step. Its controls follow the same hover, focus, +open-menu, and touch behavior without moving the transcript. Assistant `sent_at` is recorded once on the +execution host when the message enters the journal, survives reload/fork, and +never enters provider requests. The footer uses the last assistant timestamp, +formats time in the viewer's locale, and exposes the full date accessibly. + +**Fork from here** includes the selected response. **Rewind to here…** confirms +before removing later conversation and restoring tracked files where supported. +The committed response endpoint includes trailing tool results: fork uses its +inclusive sequence, rewind the next sequence. Commands retain the existing +root-only scope, expected-history-revision guards, and local errors. Rewind is +unavailable during running root work or at the latest endpoint; disconnected, +child, and uncertain-endpoint footers do not show an empty history menu. User +message actions retain their existing behavior. A large image attachment must not replace its message with a “Read stored message” button. Mounted user/assistant rows automatically fetch referenced transcript @@ -2105,24 +2137,39 @@ reveals/focuses the window, dialogs guard the action, and no web hotkey is insta ### Saved-session navigation [`session-sidebar.tsx`](../packages/app/src/session-sidebar.tsx) projects the SDK's -bounded per-host catalogs into host sections, virtual directory headers and compact -session rows in one scroll area. Group within each host by exact `cwd`: worktrees remain separate, directories with matching names show -a distinguishing parent suffix, and full paths remain available in labels and -titles. Groups follow their first catalog occurrence; sessions retain server -pin/recency order. Only loaded pages are grouped; Load more retains the SDK's -existing page/cache limits. Each directory initially shows at most seven sessions; -More reveals seven additional loaded sessions per click. Only once all loaded -sessions in the directory are visible does Less replace More; Less resets to seven. -Expansion is local to the mounted host list (up to 64 directory preferences); -route navigation reveals an older selected session by expanding its directory. -Sidebar labels never lease root views. +bounded per-host catalogs into one virtualized **Projects** list shared by desktop +and web. Group by verified runtime identity and exact cwd: worktrees remain +separate, matching names on one host show a distinguishing parent suffix, and +full paths are available on focus/hover. Local and remote directories interleave +by their newest loaded session update, with stable identity tie breaks; sessions +inside each directory retain server pin/recency order. Directory headings are +text-only, with a disclosure caret on hover/focus. Remote directories carry a +host label and connection mark. Their compact, theme-native details popover shows +host/status, a secondary connection address (SSH user/host/port where applicable, +omitted when identical to the host name), a wrapping path, and left-aligned +reconnect/server management actions. Duplicate display names expose their full +disambiguated identity in the details, without row truncation. Local folders omit host metadata +unless unavailable. Temporary disconnects retain SDK-stale rows but never live +activity indicators; explicit Disconnect still disposes the catalog. + +Only loaded pages are grouped. Host-labelled Load more controls retain independent +SDK cursors and page/cache limits; directory More is disclosure, not a fetch. +Each directory initially shows at most seven sessions. More reveals seven +additional loaded sessions per click; Less appears only when all are shown and +resets to seven. Expansion is mounted state (64 directories per host), released +when that host detaches. Exact host/path collapse retains the existing bounded v1 +window preferences. Only route navigation reveals an older selected session; +polling never undoes a deliberate collapse. Host-scoped keys also own hover, +scroll anchors, actions and drag sources. Catalog snapshots are observed directly, +not mirrored into Query or component state. Summary requests are partitioned by +host and include only rendered/overscan rows. Sidebar labels never lease root views. New session, Search sessions and Settings are the top destinations; execution-host management stays at the end of the scrollable content. The brand/window controls -and New session remain pinned; Search, Settings, host sections, and Servers share +and New session remain pinned; Search, Settings, directory groups, and Servers share one scroll area. A theme-derived hairline and 12 px soft fade appear below the pinned header only after scrolling, with a reduced-motion-aware opacity transition. -Host headings show connection status and collapse independently. Each pane's tab strip sits above the shared [`SessionTopBar`](../packages/app/src/session-top-bar.tsx): host/project, selected +Only directory groups collapse; there are no host headings. Each pane's tab strip sits above the shared [`SessionTopBar`](../packages/app/src/session-top-bar.tsx): host/project, selected agent, current activity and scoped actions. Chat, REPL and trace/span views use this same component, including loading and unavailable states. It owns the fixed-position Chat / REPL / Trace single-selection view controls and a separate @@ -2339,6 +2386,12 @@ an optional typed `xstyle` extension where appropriate. Base UI `render` and cannot contain its own close/menu button. App-specific data fetching belongs in app controllers/hooks, not in UI controls. +Shared Dialog/AlertDialog scrolling belongs to the UI component's Base UI +viewport: popups use natural content height and move as a whole over a fixed +backdrop. Short dialogs remain centered; tall dialogs retain the former top +spacing. Sheet and explicitly bounded picker compositions keep their own internal +scrolling. Consumers should not add wrappers to implement default dialog scrolling. + Use `stylex.create` and `stylex.props` for authored visuals and import shared variables from `@whip/ui/tokens.stylex`. The `.stylex` suffix is required for cross-package static resolution. Do not add Tailwind, CSS-in-JS runtime injection, @@ -2742,6 +2795,8 @@ node apps/web/scripts/snapshot-refresh.mjs node apps/web/scripts/session-tabs.mjs node apps/web/scripts/workspace-layout.mjs node apps/web/scripts/sidebar.mjs +node apps/web/scripts/agents.mjs # isolated agent-editor fixture; no daemon needed +node apps/web/scripts/directory-sidebar.mjs node apps/web/scripts/session-search.mjs node apps/web/scripts/performance.mjs # Actual Safari on macOS, distinct from Playwright WebKit: diff --git a/docs/models-providers.md b/docs/models-providers.md index d40210657..de22a2266 100644 --- a/docs/models-providers.md +++ b/docs/models-providers.md @@ -376,10 +376,11 @@ configuration. A configured route alone does not mean an account is connected. Sign-in preserves current model defaults. Select an advertised subscription model explicitly, for example `/model gpt-5.5 openai-codex`. The new-session and conversation model menus include discovered models and identify the provider -for each choice, including when API and subscription routes share a model name. To use the -subscription for titles and compaction as well, select it under Settings → -Agents & execution → Context compaction. Existing compaction settings still -apply independently to every conversation. +for each choice, including when API and subscription routes share a model name. +Automatic compaction and titles follow the conversation's subscription route. +Existing saved custom compaction routes remain separate overrides; reset Summary +model to Automatic under Settings → Agents & execution → Context compaction to +follow the conversation again. The adapter uses streamed Responses with `store:false`. Text, images on advertised vision models, reasoning summaries, and `rlm_exec` tool round trips @@ -498,11 +499,36 @@ a charge or the route is known to be free. ## Compaction model -Compaction summarizes with a separate, cheaper model: -`compactModel`/`compactProvider` in config, defaulting to -`deepseek-v4-flash-0731` (`config.DefaultCompactModel`), falling back to the -conversation's own model. `/compact [provider]` picks the summarizer -by hand. Mechanics: [agent-loop.md](agent-loop.md#compaction). +Compaction is **Automatic** by default: each agent summarizes older active +context using its own conversation model and provider. It needs no additional +provider connection and does not delete the raw transcript. Automatic session +titles use the same route selection. + +An empty or omitted `compactModel` selects Automatic; `compactProvider` is then +ignored. Existing explicitly saved models, including the former DeepSeek default, +remain custom overrides. In Settings → Agents & execution, use **Advanced +compaction settings** to select a custom model/provider together from the existing +catalog picker, or reset to Automatic. Settings saves are revision-checked and +apply when a runtime is created or reloaded; the session inspector can apply the +host defaults and reload its idle session. `/compact [provider]` also +selects a custom summarizer. + +`compactPct: 0` (or omitted) means Automatic, currently **50%** of the conversation +model's context window. Custom thresholds accept integers from **10–90%**. This +controls when to summarize, not a compression ratio. Older saved out-of-range +values remain loadable and use their existing clamped effective threshold; new +edits must use the supported range. Provider-reported prompt usage drives the +trigger, with an estimate when usage is unavailable. If the context window is +unknown, only reactive context-limit recovery applies. + +A custom route that cannot be resolved falls back to the conversation route. +Compaction also checks a custom route's known context capacity before sending the +summary. Runtime fallback is bounded and only follows a definite safe rejection, +not uncertain completion, partial output, cancellation, or accounting/budget +failure. Both attempted routes retain normal accounting. A notice explains a +fallback, and the successful summary's trace records the actual model/provider +and fallback reason. Automatic never selects another vendor or ranks models by +price. Mechanics: [agent-loop.md](agent-loop.md#context-focusing). ## Read next diff --git a/docs/roadmap.md b/docs/roadmap.md index b23cae6e5..f3fbf9fbd 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -153,6 +153,10 @@ in reduced-motion support and bounded loading. See [startup splash](../.ai-docs/plans/startup-splash/README.md). - [x] All 66 TUI themes, automatic appearance, custom-theme resolution and themed read-only code, with deterministic generation and component contrast checks. +- [x] Completed agent-response date/copy/history footer in web and desktop. + Fork and confirmed rewind retain the selected response, with host-recorded + timestamps and existing theme/accessibility controls. See + [agent response controls](../.ai-docs/plans/agent-message-controls/README.md). - [x] Packaged browser assets in the executable; no production Node server. - [ ] Single out-of-process web gateway: socket-only daemon by default, foreground `whip web`, and optional owned child via `WHIP_NETWORK=1`. This supersedes the diff --git a/docs/web-app.md b/docs/web-app.md index 85960b5ac..5ecbef02b 100644 --- a/docs/web-app.md +++ b/docs/web-app.md @@ -49,7 +49,12 @@ share profiles; tabs and split layouts remain separate per browser window. Execution hosts refreshes profiles on open, browser focus and Local reconnect. Previously saved browser-only addresses are available for explicit import. -The sidebar groups sessions by host and then directory. Different hosts can be +The sidebar lists directories across hosts in one recent-first Projects list. +Project headings are text-only. Remote directories show a host name and connection +status, with a compact details popover; local directories stay unlabelled. Groups remain distinct by exact host and path. Directory collapse +and seven-at-a-time More/Less behavior are unchanged. Temporary disconnects keep +stale catalog rows visible; explicit Disconnect clears that host's catalog. +Different hosts can be open in the same tab strip and split panes. Disconnecting one host leaves the others usable, and its tabs stay in place with connection feedback. Disconnect changes browser observation, not the remote daemon's accepted work. If Local @@ -421,6 +426,20 @@ acceptance evidence for the gateway migration. Current migration checks and any unperformed device/manual acceptance are tracked separately in the [gateway acceptance plan](../.ai-docs/plans/web-gateway/README.md). +### Agent response controls — September 27, 2026 + +Run `npm run pack:web && node apps/web/scripts/user-messages.mjs` against isolated +fake-provider daemons. The script verifies the packed renderer before compiling +the fixture, then checks one completed-response date/copy/history footer in +Chromium and Firefox: streaming suppression, local time preserved on reload, +copy success and denied-write retry, hover/focus/menu-open behavior, left +alignment, light/dark/Claude Code themes, narrow layouts and 44px touch targets. +Real fork and confirmed rewind commands retain the selected response and its +timestamp, exclude only later conversation, and leave the original intact on +fork. Latest-response rewind is disabled. Screenshots are written under +`/tmp/whip-user-message-results`. These checks exercise the shared web/desktop +renderer in browsers; they are not a separate native desktop acceptance run. + ### Multiple execution hosts — September 8, 2026 The production app passed `apps/web/scripts/multiple-hosts.mjs` in Chromium 153 diff --git a/internal/agent/agent.go b/internal/agent/agent.go index 30e63d8a0..20ed32973 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "math" - "net/url" "slices" "strings" "sync" @@ -76,6 +75,8 @@ type Events struct { // it runs. took is the pre-compaction message count, estTokens the size // estimate that triggered it. OnCompactStart func(took, estTokens int) + // OnCompactFallback reports a switch to the conversation route. + OnCompactFallback func(reason string) // OnCompaction includes the pre-compaction history so durable stores can // preserve the raw tail behind the derived summary. OnCompaction func(summary string, cutoff int, before []llm.Message, info CompactInfo) @@ -107,12 +108,14 @@ type ModelRoute struct { // CompactInfo reports how one compaction ran: which model wrote the summary // and what that call spent. Model is the bare model id when the compaction // ran on the conversation's own client, or " @ " when a dedicated -// compaction client (a different provider route) wrote it. Usage is the -// summary call's tokens (zero when the provider didn't report any). +// compaction client (a different provider route) wrote it. Usage includes +// both routes when a rejected custom request falls back (zero when unreported). type CompactInfo struct { - Model string - Usage llm.Usage - Pinned bool // the opening user message was retained before the raw tail + Model string + Provider string + Fallback string // visible diagnostic when the conversation route replaces a custom route + Usage llm.Usage + Pinned bool // the opening user message was retained before the raw tail } // Agent holds one conversation. @@ -143,10 +146,13 @@ type Agent struct { ContextLimit int // CompactClient and CompactModel run the compaction summary; nil/"" uses // the conversation's own client and model. - CompactClient *llm.Client - CompactModel string - CompactProvider string - CompactPricing llm.Pricing + CompactClient *llm.Client + CompactModel string + CompactProvider string + CompactPricing llm.Pricing + CompactContextLimit int // dedicated route's advertised context limit (zero when unknown) + CompactMaxTokens int // dedicated route's configured output limit (zero when unknown) + CompactFallback string // setup diagnostic when a custom route is unavailable // CompactThreshold is the fraction of ContextLimit at which Turn compacts // proactively; 0 uses defaultCompactThreshold. CompactThreshold float64 @@ -546,7 +552,7 @@ func (a *Agent) turn(ctx context.Context, input string, parts []llm.ContentPart, a.retriedOverflow, a.compacted = true, true before := append([]llm.Message(nil), a.Messages...) took := len(before) - sum, cutoff, info, cerr := a.compactWithStart(ctx, ev.OnCompactStart) + sum, cutoff, info, cerr := a.compactWithStart(ctx, ev.OnCompactStart, ev.OnCompactFallback) if cerr != nil && !llm.IsCompletedAccountingError(cerr) { if errors.Is(cerr, errNoHistory) { // The provider rejected the request and nothing is @@ -640,6 +646,10 @@ func (a *Agent) turn(ctx context.Context, input string, parts []llm.ContentPart, func (a *Agent) appendTurnMessages(ev Events, messages ...llm.Message) { for _, message := range messages { + if message.Role == "assistant" && message.SentAt == nil { + now := time.Now() + message.SentAt = &now + } if ev.OnMessage != nil { message.RawSequence = ev.OnMessage(message) } @@ -859,7 +869,7 @@ func (a *Agent) maybeCompact(ctx context.Context, ev Events) error { } before := append([]llm.Message(nil), a.Messages...) took := len(before) - sum, cutoff, info, err := a.compactWithStart(ctx, ev.OnCompactStart) + sum, cutoff, info, err := a.compactWithStart(ctx, ev.OnCompactStart, ev.OnCompactFallback) if err != nil && !llm.IsCompletedAccountingError(err) { if errors.Is(err, errNoHistory) { // No summary call was made. Later rounds may add foldable @@ -977,10 +987,10 @@ func compactTailStart(msgs []llm.Message, budget int) (start int, split bool) { // surface the compaction in the transcript. The caller records the summary // and cutoff as a compaction event so the raw log survives on disk. func (a *Agent) compact(ctx context.Context) (summary string, cutoff int, info CompactInfo, err error) { - return a.compactWithStart(ctx, nil) + return a.compactWithStart(ctx, nil, nil) } -func (a *Agent) compactWithStart(ctx context.Context, onStart func(took, estTokens int)) (summary string, cutoff int, info CompactInfo, err error) { +func (a *Agent) compactWithStart(ctx context.Context, onStart func(took, estTokens int), onFallback func(string)) (summary string, cutoff int, info CompactInfo, err error) { if len(a.Messages) <= 3 { // system + ≥1 user + tail: nothing to fold return "", 0, CompactInfo{}, errNoHistory } @@ -1032,35 +1042,12 @@ func (a *Agent) compactWithStart(ctx context.Context, onStart func(took, estToke onStart(len(a.Messages), EstimateTokens(a.Messages)) } summaryPrompt := buildSummaryPrompt(history, prior, a.ExecutionLanguage) - cli, mdl := a.CompactClient, a.CompactModel - dedicated := cli != nil - if cli == nil { - cli = a.Client - } - if mdl == "" { - mdl = a.Model - } - label := mdl - if dedicated { - // a dedicated compaction route: name the host so the transcript can - // tell a cheap summarizer apart from the conversation's own model - if u, perr := url.Parse(cli.BaseURL); perr == nil && u.Host != "" { - label = mdl + " @ " + u.Host - } - } - request := llm.Request{ - Model: mdl, - MaxTokens: 4096, // room for a real state digest; 1024 clipped multi-hour sessions - Messages: []llm.Message{ - sysPrompt, - {Role: "user", Content: summaryPrompt}, - }, - } - request.Accounting = a.CompactAccounting("compaction") - sum, usage, cerr := cli.Complete(ctx, request) - a.AddUsage(usage) // the summary call is session spend too + sum, info, cerr := a.compactionSummary(ctx, []llm.Message{ + sysPrompt, + {Role: "user", Content: summaryPrompt}, + }, onFallback) if cerr != nil && !llm.IsCompletedAccountingError(cerr) { - return "", 0, CompactInfo{}, fmt.Errorf("compaction summary failed: %w", cerr) + return "", 0, info, fmt.Errorf("compaction summary failed: %w", cerr) } summary = strings.TrimSpace(sum) kept := append([]llm.Message(nil), tail...) @@ -1075,7 +1062,8 @@ func (a *Agent) compactWithStart(ctx context.Context, onStart func(took, estToke a.usageMu.Lock() a.lastPrompt = 0 a.usageMu.Unlock() - return summary, tailStart, CompactInfo{Model: label, Usage: usage, Pinned: len(pinned) > 0}, cerr + info.Pinned = len(pinned) > 0 + return summary, tailStart, info, cerr } // CompactionRawTailStart returns the pre-compaction index where the prior @@ -1216,7 +1204,7 @@ func truncateField(s string, n int) string { // little history). It is safe to call while a turn is not in flight. func (a *Agent) ManualCompact(ctx context.Context, ev Events) error { before := append([]llm.Message(nil), a.Messages...) - sum, cutoff, info, err := a.compactWithStart(ctx, ev.OnCompactStart) + sum, cutoff, info, err := a.compactWithStart(ctx, ev.OnCompactStart, ev.OnCompactFallback) if err != nil && !llm.IsCompletedAccountingError(err) { return err } diff --git a/internal/agent/compaction_route.go b/internal/agent/compaction_route.go new file mode 100644 index 000000000..c4bc7835d --- /dev/null +++ b/internal/agent/compaction_route.go @@ -0,0 +1,124 @@ +package agent + +import ( + "context" + "errors" + "math" + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/context-labs/whip/internal/llm" +) + +// compactionSummary keeps routing request-local: title calls and descendants +// can read the configured route while a compaction is in flight. +func (a *Agent) compactionSummary(ctx context.Context, messages []llm.Message, onFallback func(string)) (string, CompactInfo, error) { + client, model, contextLimit, maxTokens := a.Client, a.Model, a.ContextLimit, a.MaxTokens + accounting := a.CallAccounting("compaction") + dedicated := a.CompactClient != nil && a.CompactModel != "" + if dedicated { + client, model = a.CompactClient, a.CompactModel + contextLimit, maxTokens = a.CompactContextLimit, a.CompactMaxTokens + accounting = a.CompactAccounting("compaction") + } + info := CompactInfo{Fallback: a.CompactFallback} + if err := ctx.Err(); err != nil { + return "", info, err + } + canFallback := dedicated && a.Client != nil && (model != a.Model || client.BaseURL != a.Client.BaseURL) + fallback := func(reason string) { + info.Fallback = reason + client, model, contextLimit, maxTokens = a.Client, a.Model, a.ContextLimit, a.MaxTokens + accounting = a.CallAccounting("compaction") + dedicated = false + if onFallback != nil { + onFallback(reason) + } + } + inputTokens := llm.EstimateTokens(messages) + outputLimit := func() int { + if limit := client.NaturalOutputLimit(model); limit > 0 { + return limit + } + limit := 4096 // room for a real state digest + if maxTokens > 0 { + limit = min(limit, maxTokens) + } + return limit + } + if dedicated && contextLimit > 0 && inputTokens > contextLimit-outputLimit() { + if !canFallback { + return "", info, errors.New("custom summarizer cannot fit this summary request") + } + fallback("Custom summarizer cannot fit this summary request; using this conversation’s model.") + } else if !dedicated && info.Fallback != "" && onFallback != nil { + onFallback(info.Fallback) + } + request := llm.Request{Messages: messages} + hadAttempt := false + for { + request.Model, request.Accounting, request.MaxTokens = model, accounting, outputLimit() + if client.NaturalOutputLimit(model) == 0 && contextLimit > inputTokens { + request.MaxTokens = min(request.MaxTokens, contextLimit-inputTokens) + } + info.Model, info.Provider = model, accounting.Provider + if dedicated { + if u, err := url.Parse(client.BaseURL); err == nil && u.Host != "" { + info.Model += " @ " + u.Host + } + } + // Native retries remain bounded by the client. Every attempt in the + // custom group must be a definite rejection, not an unknown transport + // completion or a discarded partial response, before changing routes. + copyClient := *client + safe := true + copyClient.OnRetry = func(event llm.RetryEvent) { + safe = safe && !event.Regenerating && compactionRejected(event.Err) + if client.OnRetry != nil { + client.OnRetry(event) + } + } + summary, usage, err := copyClient.Complete(ctx, request) + a.AddUsage(usage) + // A rejected custom attempt can still bill input. Keep that usage, + // including charges, without losing details of the successful summary. + previous := info.Usage + info.Usage = copyUsage(usage) + if hadAttempt { + addUsage(&info.Usage, previous) + info.Usage.Reported = usage.HasUsage() || previous.HasUsage() + info.Usage.Cost = nil // unknown unless both routes reported charges + if previous.Cost != nil && usage.Cost != nil { + cost := *previous.Cost + *usage.Cost + if !math.IsInf(cost, 0) && !math.IsNaN(cost) { + info.Usage.Cost = &cost + } + } + } + hadAttempt = true + if !dedicated || !safe || ctx.Err() != nil || summary != "" || usage.CompletionTokens != 0 || + !compactionRejected(err) || !canFallback { + return summary, info, err + } + // At most one conversation-route group. Admission and settlement still + // use the same budget, with the conversation's own price snapshot. + fallback("Custom summarizer rejected the request; using this conversation’s model.") + } +} + +func compactionRejected(err error) bool { + // A direct HTTP rejection excludes accounting/validation wrappers even + // when they contain an HTTPError. Timeouts can hide completed work. + rejection, ok := err.(*llm.HTTPError) + if !ok || rejection.ResponseStarted { + return false + } + fields := strings.Fields(rejection.Status) + if len(fields) == 0 { + return false + } + status, _ := strconv.Atoi(fields[0]) + return status >= 400 && status < 500 && status != http.StatusRequestTimeout +} diff --git a/internal/agent/compaction_route_test.go b/internal/agent/compaction_route_test.go new file mode 100644 index 000000000..eb8b47850 --- /dev/null +++ b/internal/agent/compaction_route_test.go @@ -0,0 +1,356 @@ +package agent + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/openaiauth" +) + +func compactionRouteAgent(t *testing.T, handler http.HandlerFunc) *Agent { + t.Helper() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + handler(w, r) + } + })) + t.Cleanup(server.Close) + client := llm.New(server.URL, "test") + client.MaxRetries = 1 + a := newTestAgent(client, "conversation", 1024, "system") + a.Provider = "conversation-provider" + a.ContextLimit = 16000 + a.Pricing = llm.Pricing{Prompt: "0.000002", Completion: "0.000005"} + a.CompactClient, a.CompactModel, a.CompactProvider = client, "custom", "custom-provider" + a.CompactPricing = llm.Pricing{Prompt: "0.000007", Completion: "0.000011"} + a.CompactMaxTokens = 512 + for range 6 { + a.Messages = append(a.Messages, llm.Message{Role: "user", Content: "work"}, + llm.Message{Role: "assistant", Content: strings.Repeat("completed work ", 600)}) + } + return a +} + +func TestCompactionFallbackAccountsBothRoutesAndKeepsConfiguration(t *testing.T) { + var models []string + a := compactionRouteAgent(t, func(w http.ResponseWriter, r *http.Request) { + var request llm.Request + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + return + } + models = append(models, request.Model) + if request.Model == "custom" { + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, "{\"error\":{\"message\":\"unavailable\"},\"usage\":{\"prompt_tokens\":7,\"completion_tokens\":0}}") + return + } + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"retained summary\"}}],\"usage\":{\"prompt_tokens\":10,\"completion_tokens\":3}}") + }) + var attempts []llm.ModelAttempt + var results []llm.ModelAttemptResult + a.SetModelCallBudget(attemptBudgetFunc(func(_ context.Context, attempt llm.ModelAttempt) (llm.ModelPermit, error) { + attempts = append(attempts, attempt) + return llm.ModelPermit{MaxTokens: attempt.MaxTokens, Timeout: attempt.Timeout, Settle: func(result llm.ModelAttemptResult) error { + results = append(results, result) + return nil + }}, nil + })) + var notices []string + var info CompactInfo + err := a.ManualCompact(t.Context(), Events{ + OnCompactFallback: func(reason string) { notices = append(notices, reason) }, + OnCompacted: func(_ string, _ int, value CompactInfo) { info = value }, + }) + if err != nil || !reflect.DeepEqual(models, []string{"custom", "conversation"}) { + t.Fatalf("models=%v err=%v", models, err) + } + if len(attempts) != 2 || len(results) != 2 || !results[0].Failed || results[1].Failed { + t.Fatalf("attempts=%+v results=%+v", attempts, results) + } + for i, provider := range []string{"custom-provider", "conversation-provider"} { + if attempts[i].Purpose != "compaction" || attempts[i].Provider != provider || !results[i].Dispatched { + t.Fatalf("attempt=%+v result=%+v", attempts[i], results[i]) + } + } + if attempts[0].Pricing != a.CompactPricing || attempts[1].Pricing != a.Pricing || + attempts[0].MaxTokens != 512 || attempts[1].MaxTokens != 1024 { + t.Fatalf("wrong route prices/limits: %+v", attempts) + } + if info.Model != a.Model || info.Provider != a.Provider || len(notices) != 1 || notices[0] != info.Fallback || + info.Usage.PromptTokens != 17 || info.Usage.CompletionTokens != 3 || a.Usage().PromptTokens != 17 { + t.Fatalf("info=%+v notices=%v usage=%+v", info, notices, a.Usage()) + } + if a.CompactClient != a.Client || a.CompactModel != "custom" || a.CompactProvider != "custom-provider" || a.CompactFallback != "" { + t.Fatal("runtime fallback mutated the configured route") + } +} + +func TestCompactionFallbackNeverReplaysUnsafeFailures(t *testing.T) { + for _, name := range []string{"budget", "settlement", "completed", "cancelled", "partial", "malformed", "network", "timeout", "request-timeout", "server-error", "bad-gateway", "generated-usage", "same-route", "fallback-budget"} { + t.Run(name, func(t *testing.T) { + var calls atomic.Int32 + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + a := compactionRouteAgent(t, func(w http.ResponseWriter, r *http.Request) { + calls.Add(1) + switch name { + case "completed": + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"completed summary\"}}]}") + case "partial": + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"partial summary\"}}],\"error\":{\"message\":\"incomplete\"}}") + case "malformed": + fmt.Fprint(w, "{\"choices\":[") + case "generated-usage": + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, "{\"usage\":{\"prompt_tokens\":7,\"completion_tokens\":1}}") + case "timeout": + http.Error(w, "timeout", http.StatusGatewayTimeout) + case "request-timeout": + http.Error(w, "timeout", http.StatusRequestTimeout) + case "server-error": + http.Error(w, "processing failed", http.StatusInternalServerError) + case "bad-gateway": + http.Error(w, "upstream response lost", http.StatusBadGateway) + default: + http.Error(w, "rejected", http.StatusBadRequest) + } + }) + if name == "same-route" { + a.CompactModel = a.Model + } + if name == "network" { + a.CompactClient = llm.New("https://custom.test", "test") + a.CompactClient.MaxRetries = 1 + a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(*http.Request) (*http.Response, error) { + calls.Add(1) + return nil, errors.New("connection lost after send") + })} + } + a.SetModelCallBudget(attemptBudgetFunc(func(_ context.Context, attempt llm.ModelAttempt) (llm.ModelPermit, error) { + if name == "budget" || name == "fallback-budget" && attempt.Model == a.Model { + return llm.ModelPermit{}, errors.New("budget exhausted") + } + return llm.ModelPermit{MaxTokens: attempt.MaxTokens, Timeout: attempt.Timeout, Settle: func(llm.ModelAttemptResult) error { + if name == "settlement" || name == "completed" { + return errors.New("accounting unavailable") + } + if name == "cancelled" { + cancel() + } + return nil + }}, nil + })) + before := a.MessagesSnapshot() + var journaled string + err := a.ManualCompact(ctx, Events{OnCompacted: func(summary string, _ int, _ CompactInfo) { journaled = summary }}) + wantCalls := int32(1) + if name == "budget" { + wantCalls = 0 + } + if err == nil || calls.Load() != wantCalls { + t.Fatalf("calls=%d err=%v", calls.Load(), err) + } + if name == "completed" { + if !llm.IsCompletedAccountingError(err) || journaled != "completed summary" || !strings.Contains(a.Messages[1].Content, journaled) { + t.Fatalf("completed response lost: journaled=%q err=%v", journaled, err) + } + } else if !reflect.DeepEqual(before, a.MessagesSnapshot()) { + t.Fatal("failed compaction changed history") + } + }) + } +} + +type compactionTransport func(*http.Request) (*http.Response, error) + +func (f compactionTransport) RoundTrip(request *http.Request) (*http.Response, error) { + return f(request) +} + +func TestCompactionFallbackDoesNotHideEarlierUnknownCompletion(t *testing.T) { + var custom, conversation int + a := compactionRouteAgent(t, func(w http.ResponseWriter, _ *http.Request) { + conversation++ + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"summary\"}}]}") + }) + a.CompactClient = llm.New("https://custom.test", "test") + a.CompactClient.MaxRetries = 2 + a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(*http.Request) (*http.Response, error) { + custom++ + if custom == 1 { + return nil, io.ErrUnexpectedEOF + } + return &http.Response{StatusCode: 400, Status: "400 Bad Request", Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil + })} + _, _, _, err := a.CompactNow(t.Context()) + if err == nil || custom != 2 || conversation != 0 { + t.Fatalf("custom=%d conversation=%d err=%v", custom, conversation, err) + } +} + +func TestCompactionFallbackPreflightsPreparedSummaryRequest(t *testing.T) { + for _, limit := range []int{100, 8192} { + t.Run(fmt.Sprint(limit), func(t *testing.T) { + var requests []llm.Request + a := compactionRouteAgent(t, func(w http.ResponseWriter, r *http.Request) { + var request llm.Request + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + } + requests = append(requests, request) + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"summary\"}}]}") + }) + a.CompactContextLimit = limit + a.Messages = []llm.Message{{Role: "system", Content: "system"}, {Role: "user", Content: "work"}} + a.Messages = toolPairs(a.Messages, 10, 100000, "t") + if EstimateTokens(a.Messages) < limit { + t.Fatal("fixture must exceed dedicated context before transcript preparation") + } + _, _, info, err := a.CompactNow(t.Context()) + if err != nil || len(requests) != 1 { + t.Fatalf("requests=%d err=%v", len(requests), err) + } + request := requests[0] + if limit == 100 { + if request.Model != a.Model || info.Fallback == "" || request.MaxTokens != a.MaxTokens { + t.Fatalf("preflight fallback: request=%+v info=%+v", request, info) + } + } else if request.Model != a.CompactModel || info.Fallback != "" || request.MaxTokens != a.CompactMaxTokens || + llm.EstimateTokens(request.Messages)+request.MaxTokens > limit { + t.Fatalf("prepared transcript fits: model=%s max=%d input=%d info=%+v", request.Model, request.MaxTokens, llm.EstimateTokens(request.Messages), info) + } + }) + } +} + +func TestCompactionFallbackUsesSubscriptionNaturalOutputForPreflight(t *testing.T) { + for _, fits := range []bool{false, true} { + t.Run(fmt.Sprint(fits), func(t *testing.T) { + var conversation, subscription int + a := compactionRouteAgent(t, func(w http.ResponseWriter, _ *http.Request) { + conversation++ + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"summary\"}}]}") + }) + auth := openaiauth.New(t.Context(), t.TempDir()) + defer auth.Close() + if fits { + if err := auth.Install(t.Context(), auth.Generation(), openaiauth.Credentials{ + AccessToken: "fixture", RefreshToken: "fixture", AccountID: "account", ExpiresAt: time.Now().Add(time.Hour), + }); err != nil { + t.Fatal(err) + } + } + a.CompactClient = llm.NewSubscription(auth) + a.CompactModel = "gpt-6-astra" + a.CompactMaxTokens = 128000 + a.CompactContextLimit = 64000 + if fits { + a.CompactContextLimit = 256000 + } + a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(r *http.Request) (*http.Response, error) { + subscription++ + var request map[string]any + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + } + if request["max_output_tokens"] != nil || request["max_tokens"] != nil { + t.Error("subscription request included an unsupported explicit output cap") + } + body := "data: {\"type\":\"response.completed\",\"response\":{\"status\":\"completed\",\"output\":[{\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"output_text\",\"text\":\"summary\"}]}]}}\n\n" + return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + })} + var reservation int + a.SetModelCallBudget(attemptBudgetFunc(func(_ context.Context, attempt llm.ModelAttempt) (llm.ModelPermit, error) { + reservation = attempt.MaxTokens + return llm.ModelPermit{MaxTokens: attempt.MaxTokens, Timeout: attempt.Timeout, Settle: func(llm.ModelAttemptResult) error { return nil }}, nil + })) + _, _, info, err := a.CompactNow(t.Context()) + if err != nil { + t.Fatal(err) + } + if fits { + if subscription != 1 || conversation != 0 || reservation != 128000 || info.Fallback != "" { + t.Fatalf("subscription=%d conversation=%d reservation=%d info=%+v", subscription, conversation, reservation, info) + } + } else if subscription != 0 || conversation != 1 || !strings.Contains(info.Fallback, "cannot fit") { + t.Fatalf("preflight skipped natural ceiling: subscription=%d conversation=%d info=%+v", subscription, conversation, info) + } + }) + } +} + +func TestCompactionFallbackDoesNotHideRegeneratedPartialOutput(t *testing.T) { + var conversation, custom int + a := compactionRouteAgent(t, func(w http.ResponseWriter, _ *http.Request) { + conversation++ + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"summary\"}}]}") + }) + a.CompactClient = llm.New("https://api.openai.com/v1", "fixture") + a.CompactModel = "gpt-6-astra" + a.CompactClient.MaxRetries, a.CompactClient.Regenerations = 2, 1 + a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(*http.Request) (*http.Response, error) { + custom++ + if custom == 1 { + body := "data: {\"type\":\"response.output_text.delta\",\"delta\":\"Partial\"}\n\n" + return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + } + return &http.Response{Status: "400 Bad Request", StatusCode: 400, Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil + })} + _, _, _, err := a.CompactNow(t.Context()) + if err == nil || custom != 2 || conversation != 0 { + t.Fatalf("custom=%d conversation=%d err=%v", custom, conversation, err) + } +} + +func TestCompactionFallbackHasOneBoundedConversationAttemptGroup(t *testing.T) { + var custom, conversation int + a := compactionRouteAgent(t, func(w http.ResponseWriter, r *http.Request) { + var request llm.Request + if err := json.NewDecoder(r.Body).Decode(&request); err != nil { + t.Error(err) + } + if request.Model == "custom" { + custom++ + } else { + conversation++ + } + http.Error(w, "rate limited", http.StatusTooManyRequests) + }) + a.Client.MaxRetries = 2 + _, _, info, err := a.CompactNow(t.Context()) + if err == nil || custom != 2 || conversation != 2 || info.Fallback == "" { + t.Fatalf("custom=%d conversation=%d info=%+v err=%v", custom, conversation, info, err) + } +} + +func TestCompactionFallbackRejectsSyntheticSSEHTTPStatus(t *testing.T) { + var conversation, custom int + a := compactionRouteAgent(t, func(w http.ResponseWriter, _ *http.Request) { + conversation++ + fmt.Fprint(w, "{\"choices\":[{\"message\":{\"content\":\"summary\"}}]}") + }) + a.CompactClient = llm.New("https://api.openai.com/v1", "fixture") + a.CompactModel = "gpt-6-astra" + a.CompactClient.MaxRetries = 1 + a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(*http.Request) (*http.Response, error) { + custom++ + body := "data: {\"type\":\"response.reasoning_summary_text.delta\",\"delta\":\"Thinking\"}\n\ndata: {\"type\":\"response.failed\",\"response\":{\"status\":\"failed\",\"error\":{\"code\":\"invalid_request\"}}}\n\n" + return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + })} + _, _, _, err := a.CompactNow(t.Context()) + if err == nil || custom != 1 || conversation != 0 { + t.Fatalf("custom=%d conversation=%d err=%v", custom, conversation, err) + } +} diff --git a/internal/agent/context_journal_test.go b/internal/agent/context_journal_test.go index 6945fa0d9..f8bd28da1 100644 --- a/internal/agent/context_journal_test.go +++ b/internal/agent/context_journal_test.go @@ -9,6 +9,7 @@ import ( "reflect" "strings" "testing" + "time" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/tools" @@ -51,6 +52,7 @@ func TestContextJournalRecordsOriginalMessagesExactlyOnce(t *testing.T) { } var journal []llm.Message boundaries := 0 + before := time.Now() final, err := ag.TurnParts(t.Context(), original, parts, Events{ Prefix: []llm.Message{{Role: "system", Content: "journal prefix"}}, OnMessage: func(message llm.Message) int { @@ -91,7 +93,17 @@ func TestContextJournalRecordsOriginalMessagesExactlyOnce(t *testing.T) { if len(view) != len(journal)+1 { t.Fatalf("view contains %d messages, journal contains %d", len(view), len(journal)) } - for i := range journal { + for i, message := range journal { + if message.Role == "assistant" || message.Authored { + if message.SentAt == nil || message.SentAt.Before(before) || message.SentAt.After(time.Now()) { + t.Fatalf("journal message %d has no recording timestamp: %+v", i, message) + } + } else if message.SentAt != nil { + t.Fatalf("internal message was stamped: %+v", message) + } + if view[i+1].SentAt != message.SentAt { + t.Fatalf("journal and model view timestamps diverged for message %d", i) + } if view[i+1].RawSequence != 100+(i+1)*7 { t.Fatalf("message %d lost raw sequence: %+v", i, view[i+1]) } @@ -100,6 +112,11 @@ func TestContextJournalRecordsOriginalMessagesExactlyOnce(t *testing.T) { t.Fatalf("model view did not focus independently: %+v", view[2]) } first, second := <-requests, <-requests + for _, message := range second.Messages { + if message.SentAt != nil { + t.Fatalf("recording timestamp reached provider: %+v", message) + } + } if first.Messages[2].Content != view[2].Content || second.Messages[len(second.Messages)-1].Content != "journal steer" { t.Fatalf("provider did not receive focused input then steer: %+v, %+v", first.Messages, second.Messages) } @@ -145,12 +162,74 @@ func TestContextJournalIncludesMaxTurnsFinalAnswer(t *testing.T) { if len(view) != 5 || view[4].Content != final || view[4].RawSequence != 204 { t.Fatalf("capped answer missing from retained view: %+v", view) } + if last.SentAt == nil || last.SentAt.IsZero() || view[4].SentAt != last.SentAt { + t.Fatalf("finalization timestamp missing or changed: journal=%+v view=%+v", last, view[4]) + } first, second := <-requests, <-requests if len(first.Tools) != 1 || len(second.Tools) != 0 || second.Messages[len(second.Messages)-1].Role != "system" { t.Fatalf("fixture did not exercise tools-disabled final answer: %+v, %+v", first, second) } } +func TestAppendTurnMessagesRecordsAssistantTimestampOnce(t *testing.T) { + t.Parallel() + for _, role := range []string{"assistant", "user", "system", "tool"} { + t.Run(role, func(t *testing.T) { + t.Parallel() + supplied := time.Date(2025, 6, 1, 14, 30, 0, 123, time.FixedZone("offset", 3600)) + ag := &Agent{} + journal := []llm.Message{} + events := Events{OnMessage: func(message llm.Message) int { + journal = append(journal, message) + return len(journal) + }} + before := time.Now() + ag.appendTurnMessages(events, + llm.Message{Role: role, Content: "new"}, + llm.Message{Role: role, Content: "existing", SentAt: &supplied}, + ) + first := journal[0].SentAt + if role == "assistant" { + if first == nil || first.Before(before) || first.After(time.Now()) { + t.Fatalf("new assistant timestamp = %v", first) + } + } else if first != nil { + t.Fatalf("stamped %s message: %v", role, first) + } + if journal[1].SentAt != &supplied { + t.Fatal("replaced supplied timestamp") + } + ag.appendTurnMessages(events, ag.MessagesSnapshot()...) + for i, message := range ag.MessagesSnapshot() { + if message.SentAt != journal[i].SentAt || message.SentAt != journal[i%2].SentAt { + t.Fatalf("timestamp changed between append, journal and snapshot: %+v", message) + } + } + }) + } +} + +func TestContextJournalStampsPreservedPartialResponse(t *testing.T) { + t.Parallel() + ag := &Agent{} + journal := []llm.Message{} + ag.preserveModelResponse(Events{OnMessage: func(message llm.Message) int { + journal = append(journal, message) + return len(journal) + }}, llm.Message{ + Role: "assistant", Content: "partial answer", ToolCalls: []llm.ToolCall{{ID: "pending"}}, + }, llm.Usage{}, context.Canceled) + if len(journal) != 2 || journal[0].Content != "partial answer\n[response interrupted]" { + t.Fatalf("partial journal = %+v", journal) + } + if journal[0].SentAt == nil || journal[0].SentAt.IsZero() || journal[1].SentAt != nil { + t.Fatalf("partial response/tool timestamps = %+v", journal) + } + if ag.MessagesSnapshot()[0].SentAt != journal[0].SentAt { + t.Fatal("partial response timestamp differs in journal and model view") + } +} + func TestContextJournalKeepsRawSequencesAcrossCompactionAndResume(t *testing.T) { t.Parallel() const earlier = "EARLIER_DECISION: never deploy without explicit approval." diff --git a/internal/agent/model_accounting_test.go b/internal/agent/model_accounting_test.go index bf4879e8d..c24a356e7 100644 --- a/internal/agent/model_accounting_test.go +++ b/internal/agent/model_accounting_test.go @@ -40,6 +40,9 @@ func TestModelAccountingPreservesAnswerAndUnexecutedTools(t *testing.T) { if len(journal) != 3 || journal[1].Content != answer || len(journal[1].ToolCalls) != 1 || journal[2].ToolCallID != "pending" || !strings.Contains(journal[2].Content, "Not executed") { t.Fatalf("journal=%+v", journal) } + if journal[1].SentAt == nil || journal[1].SentAt.IsZero() || journal[2].SentAt != nil { + t.Fatalf("preserved answer/tool timestamps = %+v", journal) + } } func TestModelAccountingFinalAdmissionCannotBypassBudget(t *testing.T) { diff --git a/internal/config/config.go b/internal/config/config.go index 355db2eb6..29a16f17b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -128,12 +128,6 @@ func (m Model) ContextWindow() int { return m.MaxTokens } -// DefaultCompactModel is the built-in compaction-model default: the -// deepseek-v4-flash route wired into the default inference.net config. An -// empty compactModel resolves to this at apply time, falling back to the -// conversation's model when it's not in the user's config. -const DefaultCompactModel = "deepseek-v4-flash-0731" - // DefaultCompactPct is the built-in compaction threshold: compact once the // estimated context use crosses this percent of the model's context window. // 50% keeps compaction deterministic instead of letting the context bloat. @@ -146,8 +140,8 @@ type Config struct { DefaultModel string `json:"defaultModel"` DefaultProvider string `json:"defaultProvider,omitempty"` // override the model's first provider DefaultEffort string `json:"defaultEffort,omitempty"` // reasoning effort for new sessions: "" defaults to "low"; "off", "low", "medium", "high" - CompactModel string `json:"compactModel,omitempty"` // model for compaction summaries; "" = the built-in default - CompactProvider string `json:"compactProvider,omitempty"` // provider for the compaction model; "" = the model's default routing + CompactModel string `json:"compactModel,omitempty"` // model for compaction summaries; "" = each conversation's own model and provider + CompactProvider string `json:"compactProvider,omitempty"` // custom model provider; ignored when CompactModel is empty CompactPct int `json:"compactPct,omitempty"` // compact at this % of the context window; 0 = DefaultCompactPct Theme string `json:"theme,omitempty"` // "light", "dark", a user theme name (themes/.json under the config dir), or "" (auto-detect at startup) Sidebar *bool `json:"sidebar,omitempty"` // the left column of panels; nil = shown when the terminal is ≥120 cols, false = hidden at startup (ctrl+x b still toggles) @@ -631,7 +625,6 @@ func keys[V any](m map[string]V) string { func Default() *Config { return &Config{ DefaultModel: "kimi-k3-fast", - CompactModel: DefaultCompactModel, MCPImport: &MCPImport{ Claude: &MCPImportSource{Enabled: new(false)}, Codex: &MCPImportSource{Enabled: new(false)}, diff --git a/internal/config/config_test.go b/internal/config/config_test.go index fa0091196..c01f54f2f 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -25,6 +25,10 @@ func TestLoadSaveDefaults(t *testing.T) { cfg.MCPImport.Codex.Enabled == nil || *cfg.MCPImport.Codex.Enabled { t.Fatal("fresh installs must leave external MCP imports opt-in") } + if cfg.CompactModel != "" || cfg.CompactProvider != "" || cfg.CompactPct != 0 { + t.Fatalf("first-run compaction is not automatic: model=%q provider=%q percent=%d", + cfg.CompactModel, cfg.CompactProvider, cfg.CompactPct) + } cfg.DefaultModel = "glm-5.2-fast" if err := cfg.Save(); err != nil { t.Fatal(err) @@ -594,3 +598,37 @@ func TestEngineOnlyConfigurationPreservesPreference(t *testing.T) { t.Fatalf("config=%+v %v", cfg, err) } } + +func TestLoadPreservesCompactionSettings(t *testing.T) { + tests := []struct { + name string + model string + provider string + percent int + }{ + {name: "automatic"}, + {name: "automatic with ignored provider", provider: "old-provider"}, + {name: "explicit former default", model: "deepseek-v4-flash-0731", provider: "inference-net"}, + {name: "explicit missing override", model: "missing-model", provider: "missing-provider"}, + {name: "legacy low threshold", percent: 5}, + {name: "legacy high threshold", percent: 95}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + cfg := Default() + cfg.CompactModel, cfg.CompactProvider, cfg.CompactPct = test.model, test.provider, test.percent + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + loaded, err := Load() + if err != nil { + t.Fatal(err) + } + if loaded.CompactModel != test.model || loaded.CompactProvider != test.provider || loaded.CompactPct != test.percent { + t.Fatalf("saved compaction settings changed: model=%q provider=%q percent=%d", + loaded.CompactModel, loaded.CompactProvider, loaded.CompactPct) + } + }) + } +} diff --git a/internal/daemon/agent_session.go b/internal/daemon/agent_session.go index cfbd6e92b..a641b1fcd 100644 --- a/internal/daemon/agent_session.go +++ b/internal/daemon/agent_session.go @@ -193,6 +193,7 @@ func (session *AgentSession) RunTurn(ctx context.Context, input string, parts [] emit("stream.tool.output", StreamEvent{ID: id, Text: text, TurnID: turnID, PartID: session.toolPresentationID(id)}) } events.OnCompactStart = func(_, _ int) { emit("stream.notice", StreamEvent{Text: "compacting context…"}) } + events.OnCompactFallback = func(reason string) { emit("stream.notice", StreamEvent{Text: reason}) } events.OnUsage = func(usage llm.Usage) { emit("stream.usage", StreamEvent{Usage: &UsageEvent{Used: usage.PromptTokens, Size: session.agent.ContextLimit, Usage: usage}}) } @@ -205,7 +206,7 @@ func (session *AgentSession) RunTurn(ctx context.Context, input string, parts [] }) callID := session.turn.LastModelCallID session.mu.Unlock() - session.recordCompactionOutput(ctx, callID, summary, rawCutoff) + session.recordCompactionOutput(ctx, callID, summary, rawCutoff, info.Fallback) } var output string if len(parts) > 0 { diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index 2ed5b81b9..03ca29e7c 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -296,11 +296,14 @@ func (r *AgentSession) CompactNow(ctx context.Context) (clientCompaction, error) end := r.beginCommandTrace(ctx, "compact", "history.compact", "/compact") summary, cutoff, info, err := r.agent.CompactNow(ctx) rawCutoff := agent.RawCompactionCutoff(before, cutoff) + if info.Fallback != "" && r.emit != nil { + r.emit("stream.notice", StreamEvent{Text: info.Fallback}) + } if err == nil || llm.IsCompletedAccountingError(err) { r.mu.Lock() callID := r.turn.LastModelCallID r.mu.Unlock() - r.recordCompactionOutput(ctx, callID, summary, rawCutoff) + r.recordCompactionOutput(ctx, callID, summary, rawCutoff, info.Fallback) } end(summary, err) return clientCompaction{ @@ -489,13 +492,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi var err error if operation == "compaction.configure" { cfg, _, patchErr := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.CompactModel, cfg.CompactProvider = action.Model, action.Provider - if action.Model == "" { - cfg.CompactProvider = "" - return nil - } - _, _, _, err := cfg.Resolve(cfg.CompactModel, cfg.CompactProvider) - return err + return s.providers.configureCompaction(cfg, action.Model, action.Provider) }) err = patchErr if err == nil { diff --git a/internal/daemon/client_control_compaction_test.go b/internal/daemon/client_control_compaction_test.go new file mode 100644 index 000000000..2829ca2b3 --- /dev/null +++ b/internal/daemon/client_control_compaction_test.go @@ -0,0 +1,88 @@ +package daemon + +import ( + "context" + "encoding/json" + "path/filepath" + "testing" + + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +func TestClientCompactionConfigurationUsesProviderValidation(t *testing.T) { + for _, test := range []struct { + name string + model string + provider string + legacy bool + wantProvider string + wantErr bool + }{ + {name: "automatic", provider: "stale"}, + {name: "alias", model: "summary", wantProvider: "ready"}, + {name: "catalog", model: "catalog-only", wantProvider: "ready"}, + {name: "missing credentials", model: "offline-summary", wantErr: true}, + {name: "wrong provider", model: "summary", provider: "other", wantErr: true}, + {name: "disabled provider", model: "disabled-summary", wantErr: true}, + {name: "ambiguous route", model: "ambiguous", wantErr: true}, + {name: "unchanged legacy", model: "deepseek-v4-flash-0731", provider: "missing", legacy: true, wantProvider: "missing"}, + } { + t.Run(test.name, func(t *testing.T) { + providers, cfg := compactionConfigurationFixture(t) + if test.legacy { + cfg.CompactModel, cfg.CompactProvider = test.model, test.provider + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + } + before, err := providers.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + rootID := createRoot(t, store) + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + }, providers) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + result := clientCommand(t, root, "tui", "configure", "compaction.configure", map[string]string{ + "model": test.model, "provider": test.provider, + }) + if (result.Status == "failed") != test.wantErr { + t.Fatalf("configuration command = %+v, wantErr %t", result, test.wantErr) + } + after, err := providers.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + if test.wantErr { + if after.Revision != before.Revision { + t.Fatal("failed command changed configuration") + } + return + } + if result.Status != "succeeded" { + t.Fatalf("configuration command = %+v", result) + } + var settings protocol.CompactionSettingsResult + if err := json.Unmarshal([]byte(result.Output), &settings); err != nil { + t.Fatal(err) + } + if settings.Model != test.model || settings.Provider != test.wantProvider || settings.BuiltinDefault != (test.model == "") { + t.Fatalf("command settings = %+v", settings) + } + if after.CompactModel != settings.Model || after.CompactProvider != settings.Provider { + t.Fatal("command result did not match saved route") + } + }) + } +} diff --git a/internal/daemon/client_control_test.go b/internal/daemon/client_control_test.go index fe83a5913..04349249e 100644 --- a/internal/daemon/client_control_test.go +++ b/internal/daemon/client_control_test.go @@ -610,6 +610,130 @@ func TestTurnSnapshotAndRewindAreDaemonOwnedAndIdempotent(t *testing.T) { } } +// Use the real transcript reader and command path: a response endpoint is a raw +// storage coordinate, not its last prose row or an index in the compacted view. +func TestResponseEndpointForkAndRewindKeepTrailingTools(t *testing.T) { + for _, step := range []int{1, 3} { + t.Run(fmt.Sprintf("sequence-step-%d", step), func(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + rootID := createRoot(t, store) + stamp := time.Date(2025, 6, 1, 14, 30, 0, 123, time.UTC) + firstCall := llm.ToolCall{ID: "first", Type: "function"} + firstCall.Function.Name = "exec" + lastCall := llm.ToolCall{ID: "last", Type: "function"} + lastCall.Function.Name = "exec" + messages := []llm.Message{ + {Role: "user", Content: "earlier", Authored: true}, + {Role: "assistant", Content: "legacy answer"}, + {Role: "user", Content: "selected response request", Authored: true}, + {Role: "assistant", Content: "progress", ToolCalls: []llm.ToolCall{firstCall}, SentAt: &stamp}, + {Role: "tool", Content: "first result", ToolCallID: firstCall.ID, Name: "exec"}, + {Role: "user", Content: "internal delivery"}, + {Role: "assistant", Content: "selected answer", ToolCalls: []llm.ToolCall{lastCall}, SentAt: &stamp}, + {Role: "tool", Content: "trailing result", ToolCallID: lastCall.ID, Name: "exec"}, + {Role: "user", Content: "later request", Authored: true}, + {Role: "assistant", Content: "later answer"}, + } + // Save's empty placeholders model legacy sparse raw history. Both + // compacted model indices and page indices differ from command cuts. + raw := make([]llm.Message, len(messages)*step+1) + for i, message := range messages { + raw[(i+1)*step] = message + } + if err := store.Save(rootID, 1, raw, "model", "provider"); err != nil { + t.Fatal(err) + } + if err := store.RecordRawCompaction(t.Context(), rootID, rootID, 2*step, "earlier summary", false); err != nil { + t.Fatal(err) + } + if err := store.Close(); err != nil { + t.Fatal(err) + } + store = openStore(t, path) + runner := &compactingRunner{fakeRunner: &fakeRunner{}} + owner, err := New(store, func(_ context.Context, _ session.Meta, history []llm.Message) (Components, error) { + if len(history) != 9 || history[0].Role != "system" || history[0].RawSequence != 2*step { + t.Fatalf("fixture did not restore compacted raw view: %+v", history) + } + runner.history = history + return Components{Runner: runner}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + root, err := owner.Open(rootID) + if err != nil { + t.Fatal(err) + } + readPage := func(id string) session.BoundedTranscriptPage { + t.Helper() + page, err := store.ReadTranscriptPage(t.Context(), id, id, session.TranscriptReadOptions{ + ThroughSeq: -1, Limit: 128, MaxBytes: 64 * 1024, + }) + if err != nil { + t.Fatal(err) + } + return page + } + page := readPage(rootID) + if len(page.Messages) != len(messages) { + t.Fatalf("raw page has %d messages, want %d", len(page.Messages), len(messages)) + } + for i, entry := range page.Messages { + if entry.Seq != (i+1)*step || entry.Message == nil || entry.Message.RawSequence != entry.Seq { + t.Fatalf("transcript remapped raw sequence: %+v", entry) + } + } + endpoint := page.Messages[7].Seq + revision := strconv.FormatInt(page.HistoryRevision, 10) + fork := clientCommand(t, root, "web", "response-fork", "session.fork", map[string]any{ + "cut": endpoint, "expected_revision": revision, + }) + if fork.Status != "succeeded" { + t.Fatalf("fork: %+v", fork) + } + if got := readPage(fork.Output).Messages; !reflect.DeepEqual(got, page.Messages[:8]) { + t.Fatalf("fork did not retain complete response including trailing tools: %+v", got) + } + if !reflect.DeepEqual(readPage(rootID), page) { + t.Fatal("fork mutated source history") + } + // Characterize existing user actions too: cut=user seq includes the + // selected user in a fork, regardless of a UI label saying "before". + userFork := clientCommand(t, root, "web", "user-fork", "session.fork", map[string]any{ + "cut": page.Messages[2].Seq, "expected_revision": revision, + }) + if userFork.Status != "succeeded" || !reflect.DeepEqual(readPage(userFork.Output).Messages, page.Messages[:3]) { + t.Fatalf("user fork boundary changed: %+v", userFork) + } + rewind := clientCommand(t, root, "web", "response-rewind", "history.rewind", map[string]any{ + "cut": endpoint + 1, "expected_revision": revision, + }) + if rewind.Status != "succeeded" { + t.Fatalf("rewind: %+v", rewind) + } + rewound := readPage(rootID) + if !reflect.DeepEqual(rewound.Messages, page.Messages[:8]) || rewound.HistoryRevision != page.HistoryRevision+1 { + t.Fatalf("rewind did not retain complete response at new revision: %+v", rewound) + } + if len(runner.replaced) != 8 || runner.replaced[7].RawSequence != endpoint || runner.replaced[7].ToolCallID != lastCall.ID { + t.Fatalf("runner replacement lost response endpoint: %+v", runner.replaced) + } + if runner.replaced[1].SentAt != nil || runner.replaced[6].SentAt == nil || !runner.replaced[6].SentAt.Equal(stamp) { + t.Fatal("rewind restamped history or lost assistant timestamp") + } + stale := clientCommand(t, root, "web", "stale-response-rewind", "history.rewind", map[string]any{ + "cut": endpoint + 1, "expected_revision": revision, + }) + if stale.Status != "failed" || !reflect.DeepEqual(readPage(rootID), rewound) { + t.Fatalf("stale action changed history: %+v", stale) + } + }) + } +} + func TestGoalRunUsesOneControlCommandAndStartsTheGoalTurn(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) diff --git a/internal/daemon/compaction_fallback_test.go b/internal/daemon/compaction_fallback_test.go new file mode 100644 index 000000000..6d2610f74 --- /dev/null +++ b/internal/daemon/compaction_fallback_test.go @@ -0,0 +1,168 @@ +package daemon + +import ( + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "sync/atomic" + "testing" + + "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" + "github.com/context-labs/whip/internal/tools" +) + +func compactionFallbackHistory() []llm.Message { + history := []llm.Message{{Role: "system", Content: "system"}} + for range 8 { + history = append(history, + llm.Message{Role: "user", Authored: true, Content: strings.Repeat("history ", 1000)}, + llm.Message{Role: "assistant", Content: strings.Repeat("response ", 1000)}, + ) + } + return history +} + +func TestCompactionFallbackPersistsNoticeRouteAndBothCharges(t *testing.T) { + for _, automatic := range []bool{false, true} { + t.Run(fmt.Sprintf("automatic=%t", automatic), func(t *testing.T) { + var customCalls atomic.Int32 + store, root, _ := modelAccountingRuntime(t, func(w http.ResponseWriter, r *http.Request) { + request, ok := modelAccountingRequest(t, w, r) + if !ok { + return + } + if request.Model == "custom-model" { + customCalls.Add(1) + w.WriteHeader(http.StatusBadRequest) + fmt.Fprint(w, "{\"error\":{\"message\":\"not supported\"},\"usage\":{\"prompt_tokens\":7,\"completion_tokens\":0}}") + return + } + modelAccountingReply(w, request, "retained summary", modelAccountingUsage()) + }, compactionFallbackHistory(), func(a *agent.Agent) { + a.ContextLimit = 4000 + a.CompactClient, a.CompactModel, a.CompactProvider = a.Client, "custom-model", "custom-provider" + a.CompactPricing = llm.Pricing{Prompt: "0.000007", Completion: "0.000011"} + }) + if automatic { + receipt, err := root.Submit(t.Context(), "continue") + if err != nil { + t.Fatal(err) + } + if done := waitReceipt(t, receipt); done.Err != nil { + t.Fatal(done.Err) + } + } else if result := clientCommand(t, root, "tui", "compact-fallback", "history.compact", protocol.EmptyParams{}); result.Status != "succeeded" { + t.Fatalf("manual compaction=%+v", result) + } + accounting := modelAccountingSummary(t, store, root, "", true) + calls, cost := int64(2), int64(94) // custom: 7*7; conversation: 10*2 + 5*5 + if automatic { + calls, cost = 3, 139 + } + if customCalls.Load() != 1 || accounting.ReportedCalls != calls || accounting.EstimatedCostMicros != cost || accounting.UnknownCostCalls != 0 { + t.Fatalf("accounting=%+v custom calls=%d", accounting, customCalls.Load()) + } + spans, err := store.SpansForTrace(t.Context(), root.ID(), "") + if err != nil { + t.Fatal(err) + } + var folded, rejected int + var reason string + for _, span := range spans { + var attrs map[string]any + if err := json.Unmarshal(span.Attrs, &attrs); err != nil { + t.Fatal(err) + } + if span.Kind != session.SpanKindLLM || attrs["purpose"] != "compaction" { + continue + } + if span.Status == session.SpanStatusError { + rejected++ + if attrs["provider"] != "custom-provider" || attrs["compaction_fallback"] != nil { + t.Fatalf("rejected span attrs=%v", attrs) + } + continue + } + folded++ + reason, _ = attrs["compaction_fallback"].(string) + ref, _ := attrs["output_ref"].(string) + body, _, err := store.ReadContent(t.Context(), ref, root.ID(), root.AgentID(), 0, session.MaxContentRead) + if err != nil || string(body) != "retained summary" || attrs["model"] != "root-model" || attrs["provider"] != "provider" || reason == "" { + t.Fatalf("successful fallback span attrs=%v body=%q err=%v", attrs, body, err) + } + } + if folded != 1 || rejected != 1 || len(store.Compactions(root.ID())) != 1 { + t.Fatalf("folded=%d rejected=%d persisted=%d", folded, rejected, len(store.Compactions(root.ID()))) + } + events, _, err := store.ReplayEvents(t.Context(), root.ID(), 0, 1000) + if err != nil { + t.Fatal(err) + } + found := false + for _, event := range events { + if event.Kind == "stream.notice" && strings.Contains(string(event.Payload.Inline), reason) { + found = true + } + } + if !found { + t.Fatal("fallback diagnostic was not emitted as a stream.notice") + } + }) + } +} + +func TestRecursiveCompactionAutoUsesChildRouteAndCustomIsInherited(t *testing.T) { + for _, custom := range []bool{false, true} { + t.Run(fmt.Sprintf("custom=%t", custom), func(t *testing.T) { + var model string + var maxTokens int + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + request, ok := modelAccountingRequest(t, w, r) + if !ok { + return + } + model, maxTokens = request.Model, request.MaxTokens + modelAccountingReply(w, request, "summary", modelAccountingUsage()) + })) + defer server.Close() + parent := agent.NewRuntime(llm.New("https://parent.invalid", "test"), "parent-model", 128, "system", tools.NewServices()) + defer parent.Services.Close() + parent.ModelName, parent.Provider = "parent", "parent-provider" + parent.ResolveModel = func(_, _ string) (agent.ModelRoute, error) { + return agent.ModelRoute{Client: llm.New(server.URL, "test"), Model: "child-model", ModelName: "child", Provider: "child-provider", ContextLimit: 8192, MaxTokens: 1024}, nil + } + if custom { + parent.CompactClient, parent.CompactModel, parent.CompactProvider = llm.New(server.URL, "test"), "custom-model", "custom-provider" + parent.CompactContextLimit, parent.CompactMaxTokens = 64000, 256 + parent.CompactPricing = llm.Pricing{Prompt: "0.000007"} + } else { + // An unavailable custom route still behaves like Auto in a child. + parent.CompactFallback = "Custom summarizer unavailable; using this conversation’s model." + } + child, _, _, err := cloneRuntimeAgent(parent, tools.NewServices(), map[string]any{"model": "child"}) + if err != nil { + t.Fatal(err) + } + defer child.Services.Close() + child.Messages = compactionFallbackHistory() + _, _, info, err := child.CompactNow(t.Context()) + if err != nil { + t.Fatal(err) + } + if custom { + if model != parent.CompactModel || maxTokens != 256 || info.Provider != parent.CompactProvider || child.CompactClient != parent.CompactClient || + child.CompactContextLimit != 64000 || child.CompactMaxTokens != 256 || child.CompactPricing != parent.CompactPricing { + t.Fatalf("custom inheritance: model=%s max=%d info=%+v", model, maxTokens, info) + } + } else if model != "child-model" || maxTokens <= 0 || maxTokens > 1024 || info.Provider != "child-provider" || info.Model != "child-model" || + child.CompactClient != nil || child.CompactModel != "" || info.Fallback != parent.CompactFallback { + t.Fatalf("Auto used the wrong route: model=%s max=%d info=%+v", model, maxTokens, info) + } + }) + } +} diff --git a/internal/daemon/context_history_test.go b/internal/daemon/context_history_test.go index 721229fe2..724079b1e 100644 --- a/internal/daemon/context_history_test.go +++ b/internal/daemon/context_history_test.go @@ -268,6 +268,11 @@ func TestCurrentTurnHistorySurvivesCompactionAndCommitsOnce(t *testing.T) { if len(rows.Messages) != 4 || rows.Messages[0].Message.Content != original { t.Fatalf("journal rows=%d", len(rows.Messages)) } + for _, row := range rows.Messages { + if row.Message.Role == "assistant" && (row.Message.SentAt == nil || row.Message.SentAt.IsZero()) { + t.Fatalf("root journal lost assistant recording timestamp: %+v", row) + } + } // A fork reads the same original from its own durable source after reopen. fork, err := store.Fork(root.ID(), rows.ThroughSeq, "fork") if err != nil { diff --git a/internal/daemon/provider_client_behavior_test.go b/internal/daemon/provider_client_behavior_test.go index 8771b5604..6691913b2 100644 --- a/internal/daemon/provider_client_behavior_test.go +++ b/internal/daemon/provider_client_behavior_test.go @@ -133,7 +133,10 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if key != "private-api-key" { return nil, errors.New("bad key") } - return []llm.ModelInfo{{ID: "fixture-model", SupportsTools: new(true), OutputModalities: []string{"text"}}}, nil + return []llm.ModelInfo{ + {ID: "fixture-model", SupportsTools: new(true), OutputModalities: []string{"text"}}, + {ID: "compact-model"}, + }, nil } service.login = func(_ context.Context, code func(string, string)) (providerLoginIdentity, error) { code("https://example.test/verify", "display-code") diff --git a/internal/daemon/provider_service.go b/internal/daemon/provider_service.go index 25f1adc00..434fb44bd 100644 --- a/internal/daemon/provider_service.go +++ b/internal/daemon/provider_service.go @@ -237,8 +237,11 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon enabled := *p.BrandIcons c.BrandIcons = &enabled } - if p.CompactPercent != nil && (*p.CompactPercent < 0 || *p.CompactPercent > 100) { - return errors.New("invalid compaction percentage") + if p.CompactPercent != nil && *p.CompactPercent != c.CompactPct { + percent := *p.CompactPercent + if percent != 0 && (percent < 10 || percent > 90) { + return errors.New("compaction percentage must be 0 (automatic) or between 10 and 90") + } } if p.GoalMaxRounds != nil && *p.GoalMaxRounds < 0 { return errors.New("invalid goal round limit") @@ -268,11 +271,17 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon } c.DefaultPermissionMode = mode } - if p.CompactModel != nil { - c.CompactModel = *p.CompactModel - } - if p.CompactProvider != nil { - c.CompactProvider = *p.CompactProvider + if p.CompactModel != nil || p.CompactProvider != nil { + model, provider := c.CompactModel, c.CompactProvider + if p.CompactModel != nil { + model = *p.CompactModel + } + if p.CompactProvider != nil { + provider = *p.CompactProvider + } + if err := s.configureCompaction(c, model, provider); err != nil { + return err + } } if p.CompactPercent != nil { c.CompactPct = *p.CompactPercent @@ -312,6 +321,24 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon return runtimeConfiguration(c, revision), nil } +// configureCompaction validates new custom selections without revalidating an +// unchanged saved override when a settings form resends it. +func (s *ProviderService) configureCompaction(c *config.Config, model, provider string) error { + if model == "" { + c.CompactModel, c.CompactProvider = "", "" + return nil + } + if model == c.CompactModel && provider == c.CompactProvider { + return nil + } + selection := s.providerSelection(c, s.CatalogsFor(c), model, provider) + if !selection.Ready { + return errors.New("select a compaction model available on a connected provider") + } + c.CompactModel, c.CompactProvider = selection.Model, selection.Provider + return nil +} + func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup) (RuntimeConfiguration, error) { if p.Revision == "" { return RuntimeConfiguration{}, errors.New("configuration revision is required") diff --git a/internal/daemon/provider_service_test.go b/internal/daemon/provider_service_test.go index d416b5732..04f825942 100644 --- a/internal/daemon/provider_service_test.go +++ b/internal/daemon/provider_service_test.go @@ -267,3 +267,174 @@ func TestProviderLoginChangesWorkspaceBeforeProvisioning(t *testing.T) { t.Fatal("resumed a cancelled login") } } + +func compactionConfigurationFixture(t *testing.T) (*ProviderService, *config.Config) { + t.Helper() + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("WHIP_TEST_MISSING_COMPACTION_KEY", "") + cfg := &config.Config{ + DefaultModel: "main", + Providers: map[string]config.Provider{ + "ready": {BaseURL: "https://ready.test/v1", Auth: "none"}, + "other": {BaseURL: "https://other.test/v1", Auth: "none"}, + "offline": {BaseURL: "https://offline.test/v1", APIKeyEnv: "WHIP_TEST_MISSING_COMPACTION_KEY"}, + "disabled": {BaseURL: "https://disabled.test/v1", Auth: "none"}, + }, + Models: map[string]config.Model{ + "main": {Providers: []string{"ready"}}, + "summary": {Providers: []string{"ready"}}, + "offline-summary": {Providers: []string{"offline"}}, + "disabled-summary": {Providers: []string{"disabled"}}, + }, + DisabledProviders: []string{"disabled"}, + } + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + if err := config.SaveCatalogs(map[string]config.Catalog{ + "ready": {BaseURL: "https://ready.test/v1", Models: []config.ModelInfoLite{ + {ID: "catalog-only"}, {ID: "ambiguous"}, + }}, + "other": {BaseURL: "https://other.test/v1", Models: []config.ModelInfoLite{{ID: "ambiguous"}}}, + }); err != nil { + t.Fatal(err) + } + s := NewProviderService(t.Context(), "compaction-settings") + t.Cleanup(s.Close) + return s, cfg +} + +func TestProviderCompactionConfigurationSelections(t *testing.T) { + tests := []struct { + name string + model string + provider string + wantProvider string + wantErr bool + }{ + {name: "alias resolves provider", model: "summary", wantProvider: "ready"}, + {name: "catalog resolves provider", model: "catalog-only", wantProvider: "ready"}, + {name: "explicit route", model: "summary", provider: "ready", wantProvider: "ready"}, + {name: "automatic clears provider", provider: "stale"}, + {name: "unknown model", model: "missing", provider: "ready", wantErr: true}, + {name: "unknown provider", model: "summary", provider: "missing", wantErr: true}, + {name: "missing credentials", model: "offline-summary", wantErr: true}, + {name: "disabled provider", model: "disabled-summary", wantErr: true}, + {name: "wrong provider", model: "summary", provider: "other", wantErr: true}, + {name: "ambiguous route", model: "ambiguous", wantErr: true}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + s, _ := compactionConfigurationFixture(t) + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(ConfigurationUpdate{ + Revision: before.Revision, CompactModel: &test.model, CompactProvider: &test.provider, + CompactPercent: new(60), MaxRetries: new(3), + }) + if (err != nil) != test.wantErr { + t.Fatalf("update error = %v, wantErr %t", err, test.wantErr) + } + persisted, readErr := s.ReadConfiguration() + if readErr != nil { + t.Fatal(readErr) + } + if test.wantErr { + if persisted.Revision != before.Revision { + t.Fatal("invalid route partially saved configuration") + } + return + } + if after.CompactModel != test.model || after.CompactProvider != test.wantProvider { + t.Fatalf("compaction selection = %q %q; want %q %q", + after.CompactModel, after.CompactProvider, test.model, test.wantProvider) + } + if persisted.CompactModel != after.CompactModel || persisted.CompactProvider != after.CompactProvider { + t.Fatal("resolved model and provider were not persisted together") + } + if after.CompactPercent != 60 || after.MaxRetries != 3 { + t.Fatal("valid settings were not saved atomically") + } + }) + } +} + +func TestProviderCompactionConfigurationPreservesUnchangedLegacyOverrides(t *testing.T) { + for _, model := range []string{"deepseek-v4-flash-0731", "missing-summary"} { + t.Run(model, func(t *testing.T) { + s, cfg := compactionConfigurationFixture(t) + cfg.CompactModel, cfg.CompactProvider, cfg.CompactPct = model, "missing-provider", 95 + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(ConfigurationUpdate{ + Revision: before.Revision, CompactModel: &before.CompactModel, + CompactProvider: &before.CompactProvider, CompactPercent: &before.CompactPercent, + DefaultModel: &before.DefaultModel, DefaultProvider: &before.DefaultProvider, MaxRetries: new(4), + }) + if err != nil { + t.Fatal(err) + } + if after.CompactModel != model || after.CompactProvider != "missing-provider" || after.CompactPercent != 95 || after.MaxRetries != 4 { + t.Fatalf("legacy override was changed: %+v", after) + } + if _, err := s.UpdateConfiguration(ConfigurationUpdate{ + Revision: after.Revision, CompactProvider: new("different-missing-provider"), + }); err == nil { + t.Fatal("changed legacy route was not validated") + } + cleared, err := s.UpdateConfiguration(ConfigurationUpdate{ + Revision: after.Revision, CompactModel: new(""), CompactProvider: &after.CompactProvider, + }) + if err != nil || cleared.CompactModel != "" || cleared.CompactProvider != "" { + t.Fatalf("automatic did not clear override: %+v %v", cleared, err) + } + }) + } +} + +func TestProviderCompactionConfigurationThresholdValidation(t *testing.T) { + for _, test := range []struct { + name string + percent int + wantErr bool + }{ + {name: "automatic"}, + {name: "minimum", percent: 10}, + {name: "maximum", percent: 90}, + {name: "negative", percent: -1, wantErr: true}, + {name: "below minimum", percent: 9, wantErr: true}, + {name: "above maximum", percent: 91, wantErr: true}, + {name: "over 100", percent: 101, wantErr: true}, + } { + t.Run(test.name, func(t *testing.T) { + s, _ := compactionConfigurationFixture(t) + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(ConfigurationUpdate{ + Revision: before.Revision, CompactPercent: &test.percent, MaxRetries: new(5), + }) + if (err != nil) != test.wantErr { + t.Fatalf("threshold error = %v, wantErr %t", err, test.wantErr) + } + if !test.wantErr && after.CompactPercent != test.percent { + t.Fatalf("threshold = %d, want %d", after.CompactPercent, test.percent) + } + persisted, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + if test.wantErr && persisted.Revision != before.Revision { + t.Fatal("invalid threshold partially saved configuration") + } + }) + } +} diff --git a/internal/daemon/recursive_runtime.go b/internal/daemon/recursive_runtime.go index 83fe6042f..e8a28ced4 100644 --- a/internal/daemon/recursive_runtime.go +++ b/internal/daemon/recursive_runtime.go @@ -1356,6 +1356,8 @@ func cloneRuntimeAgent(parent *agent.Agent, services *tools.Services, arguments child.Temperature, child.TopP = parent.Temperature, parent.TopP child.CompactClient, child.CompactModel, child.CompactThreshold = parent.CompactClient, parent.CompactModel, parent.CompactThreshold child.CompactPricing, child.CompactProvider = parent.CompactPricing, parent.CompactProvider + child.CompactContextLimit, child.CompactMaxTokens = parent.CompactContextLimit, parent.CompactMaxTokens + child.CompactFallback = parent.CompactFallback child.WorkingDir = parent.WorkingDir child.ResolveModel = parent.ResolveModel return child, child.ModelName, child.Provider, nil diff --git a/internal/daemon/recursive_runtime_test.go b/internal/daemon/recursive_runtime_test.go index 37ecf7423..dd008fb9f 100644 --- a/internal/daemon/recursive_runtime_test.go +++ b/internal/daemon/recursive_runtime_test.go @@ -502,6 +502,10 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { if err != nil || len(transcript) == 0 { t.Fatalf("first transcript = %+v, %v", transcript, err) } + stamp := transcript[len(transcript)-1].SentAt + if stamp == nil || stamp.IsZero() { + t.Fatalf("child response recording timestamp missing: %+v", transcript) + } waitAgentIdle(t, first.agents[childID]) if err := owner.Close(); err != nil { t.Fatal(err) @@ -524,6 +528,8 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { } if history := restored.agent.MessagesSnapshot(); len(history) < 2 || !strings.Contains(history[len(history)-1].Content, "remembered child turn") { t.Fatalf("restored history = %+v", history) + } else if got := history[len(history)-1].SentAt; got == nil || !got.Equal(*stamp) { + t.Fatalf("child timestamp changed on restore: %v, want %v", got, stamp) } runs := &sync.Map{} second.setRunTurnHook(observeRunTurn(runs)) diff --git a/internal/daemon/spans.go b/internal/daemon/spans.go index b42641962..5d254c271 100644 --- a/internal/daemon/spans.go +++ b/internal/daemon/spans.go @@ -407,7 +407,7 @@ func (node *AgentSession) beginCommandTrace(ctx context.Context, name, command, // returned, so it is the agent's most recently settled call, and its span has // already ended; hence the patch. The compactions table keeps the summary for // recovery exactly as before. -func (node *AgentSession) recordCompactionOutput(ctx context.Context, callID, summary string, rawCutoff int) { +func (node *AgentSession) recordCompactionOutput(ctx context.Context, callID, summary string, rawCutoff int, fallback string) { if node.root == nil || callID == "" || summary == "" { return } @@ -415,9 +415,11 @@ func (node *AgentSession) recordCompactionOutput(ctx context.Context, callID, su defer cancel() value, err := node.root.store.InternContent(ctx, node.root.ID(), "prompt.summary", []byte(summary)) if err == nil { - err = node.root.store.PatchSpanAttrs(ctx, node.root.ID(), sessionstore.ModelCallSpanID(node.root.ID(), callID), map[string]any{ - "output_ref": value.ReferenceID, "output_bytes": int(value.Size), "raw_cutoff": rawCutoff, - }) + attrs := map[string]any{"output_ref": value.ReferenceID, "output_bytes": int(value.Size), "raw_cutoff": rawCutoff} + if fallback != "" { + attrs["compaction_fallback"] = fallback + } + err = node.root.store.PatchSpanAttrs(ctx, node.root.ID(), sessionstore.ModelCallSpanID(node.root.ID(), callID), attrs) } if err != nil { config.LogEvent("trace", fmt.Sprintf("compaction output of call %s: %v", callID, err)) diff --git a/internal/daemon/v2_sdk_test.go b/internal/daemon/v2_sdk_test.go index 8dc9a8d2e..c63c03d92 100644 --- a/internal/daemon/v2_sdk_test.go +++ b/internal/daemon/v2_sdk_test.go @@ -448,6 +448,18 @@ func (r *sdkFixtureRunner) Turn(ctx context.Context, input string, authored bool r.mu.Lock() r.journalStart, r.boundaryJournal = len(r.history), turnJournal{} r.mu.Unlock() + defer func() { + // The fake runner bypasses Agent.appendTurnMessages; retain the same + // recording-time contract before the daemon reads this turn's journal. + r.mu.Lock() + defer r.mu.Unlock() + for i := r.journalStart; i < len(r.history); i++ { + if r.history[i].Role == "assistant" && r.history[i].SentAt == nil { + now := time.Now() + r.history[i].SentAt = &now + } + } + }() if input == "queue:boundary" { return r.queueBoundaryTurn(ctx, input, started) } diff --git a/internal/llm/openai.go b/internal/llm/openai.go index 41b4044ab..9ac2d245b 100644 --- a/internal/llm/openai.go +++ b/internal/llm/openai.go @@ -44,10 +44,10 @@ type Message struct { // results, goal-check continuations). Internal only — never sent to the // provider. Used so input-history recall cycles only real submissions. Authored bool `json:"authored,omitempty"` - // SentAt is when the human submitted the message (local time). Internal - // only — never sent to the provider; used by the rewind picker's - // per-message timestamp. A pointer so omitempty drops it for injected and - // pre-field messages (a zero time.Time struct is never omitted). + // SentAt is when a human submitted a user message or the execution host + // recorded an assistant message. Internal only — never sent to the provider. + // A pointer so omitempty drops it for other injected and pre-field messages + // (a zero time.Time struct is never omitted). SentAt *time.Time `json:"sent_at,omitempty"` // Usage is the token accounting for the assistant response that produced // this message. Internal only — never sent to the provider; powers @@ -241,7 +241,7 @@ type ToolCall struct { // stripAuthored returns a copy of msgs with the internal Authored marker and // SentAt timestamp cleared — they're whip-local bookkeeping (input-history -// recall, the rewind picker) and must never reach the provider. It copies +// recall, transcript timestamps) and must never reach the provider. It copies // because req.Messages typically aliases the caller's conversation slice, // which must keep the fields for storage/recall. func stripAuthored(msgs []Message) []Message { @@ -526,6 +526,9 @@ type HTTPError struct { Body string Permanent bool RetryAfter time.Duration + // ResponseStarted distinguishes in-stream errors assigned a synthetic + // HTTP status from an actual HTTP rejection before response generation. + ResponseStarted bool } func (e *HTTPError) Error() string { return e.Status + ": " + e.Body } diff --git a/internal/llm/openai_test.go b/internal/llm/openai_test.go index dd65920ee..89408b21d 100644 --- a/internal/llm/openai_test.go +++ b/internal/llm/openai_test.go @@ -41,7 +41,10 @@ func TestStreamStripsAuthoredFlag(t *testing.T) { defer srv.Close() sent := time.Now() - msgs := []Message{{Role: "user", Content: "typed by me", Authored: true, SentAt: &sent}} + msgs := []Message{ + {Role: "user", Content: "typed by me", Authored: true, SentAt: &sent}, + {Role: "assistant", Content: "recorded response", SentAt: &sent}, + } if _, _, err := New(srv.URL, "test-key").Stream(context.Background(), Request{Model: "m", Messages: msgs}, nil, nil, nil); err != nil { t.Fatal(err) } @@ -51,6 +54,11 @@ func TestStreamStripsAuthoredFlag(t *testing.T) { if strings.Contains(string(body), "sent_at") { t.Fatalf("SentAt timestamp leaked to provider: %s", body) } + for _, message := range msgs { + if message.SentAt != &sent { + t.Fatalf("provider filtering mutated local timestamp: %+v", message) + } + } } func TestModels(t *testing.T) { diff --git a/internal/llm/subscription.go b/internal/llm/subscription.go index 0dc49bbc9..03f6426ae 100644 --- a/internal/llm/subscription.go +++ b/internal/llm/subscription.go @@ -35,6 +35,15 @@ func NewSubscription(auth *openaiauth.Manager) *Client { return client } +// NaturalOutputLimit returns the verified fixed output reservation for a +// transport that cannot enforce smaller request caps, or zero otherwise. +func (c *Client) NaturalOutputLimit(model string) int { + if c.openAI != nil { + return SubscriptionOutputLimit(model) + } + return 0 +} + // SubscriptionOutputLimit is a vetted natural model ceiling, not a request // parameter. Codex's subscription endpoint does not expose max_output_tokens. // Sources checked 2026-09-08: developers.openai.com/api/docs/models/{gpt, @@ -131,6 +140,7 @@ type subscriptionFailure struct { // HTTP bodies and SSE failures carry the same error, either nested or inline. // SSE has no HTTP failure status, so derive only known retryable categories. func subscriptionError(status int, body []byte) *HTTPError { + responseStarted := status == 0 var payload struct { Error *subscriptionFailure `json:"error"` subscriptionFailure @@ -154,7 +164,10 @@ func subscriptionError(status int, body []byte) *HTTPError { status = http.StatusBadRequest } } - err := &HTTPError{Status: strconv.Itoa(status) + " " + http.StatusText(status), Body: "OpenAI subscription request failed"} + err := &HTTPError{ + Status: strconv.Itoa(status) + " " + http.StatusText(status), Body: "OpenAI subscription request failed", + ResponseStarted: responseStarted, + } switch code { case "usage_limit_reached", "insufficient_quota", "quota_exceeded": err.Permanent = true diff --git a/internal/session/title.go b/internal/session/title.go index 5290ff55f..72dfffd95 100644 --- a/internal/session/title.go +++ b/internal/session/title.go @@ -11,7 +11,12 @@ import ( "github.com/context-labs/whip/internal/llm" ) -const provisionalTitleRunes = 64 +// Titles stay bounded so sidebar rows and tooltips stay readable, but long +// enough that action labels ("Archive ", "Actions for <title>") keep +// their meaning instead of clipping to an ellipsis at sentence length. The cap +// matches the catalog query's 128-rune substr budget (catalog_page.go), so a +// stored title never gets cut a second time on the way to the UI. +const provisionalTitleRunes = 128 // TitleInitialization is returned only by the admission that committed the // initial title. Prompt contains authored text, never expanded attachments. diff --git a/internal/session/title_admission_test.go b/internal/session/title_admission_test.go index 1dbeaf038..c80abb017 100644 --- a/internal/session/title_admission_test.go +++ b/internal/session/title_admission_test.go @@ -36,7 +36,7 @@ func TestTitleInitializedAtAdmission(t *testing.T) { name, kind, payload, prompt, title string }{ {"text", "submit", " Fix\n the bug ", " Fix\n the bug ", "Fix the bug"}, - {"unicode", "steer", strings.Repeat("界", 65), strings.Repeat("界", 65), strings.Repeat("界", 63) + "…"}, + {"unicode", "steer", strings.Repeat("界", provisionalTitleRunes+1), strings.Repeat("界", provisionalTitleRunes+1), strings.Repeat("界", provisionalTitleRunes-1) + "…"}, {"multipart", "submit.parts", `{"text":"Fix","parts":[{"type":"text","text":"the bug"},{"type":"image_url","image_url":{"url":"ignored"}}],"attachments":[{"kind":"text","name":"ignored.txt"}]}`, "Fix\nthe bug", "Fix the bug"}, {"parts only", "steer.parts", `{"parts":[{"type":"text","text":"First"},{"type":"text","text":"second"}]}`, "First\nsecond", "First second"}, } { diff --git a/internal/session/title_test.go b/internal/session/title_test.go index 38aee3793..056048719 100644 --- a/internal/session/title_test.go +++ b/internal/session/title_test.go @@ -11,7 +11,7 @@ import ( ) func TestProvisionalTitle(t *testing.T) { - long := strings.Repeat("界", 65) + long := strings.Repeat("界", provisionalTitleRunes+1) tests := []struct { name string messages []llm.Message @@ -22,8 +22,8 @@ func TestProvisionalTitle(t *testing.T) { {Role: "user", Content: "injected"}, {Role: "user", Content: " authored\n title ", Authored: true}, }, want: "authored title"}, - {name: "exact boundary", messages: []llm.Message{{Role: "user", Content: strings.Repeat("界", 64), Authored: true}}, want: strings.Repeat("界", 64)}, - {name: "truncates by rune", messages: []llm.Message{{Role: "user", Content: long, Authored: true}}, want: strings.Repeat("界", 63) + "…"}, + {name: "exact boundary", messages: []llm.Message{{Role: "user", Content: strings.Repeat("界", provisionalTitleRunes), Authored: true}}, want: strings.Repeat("界", provisionalTitleRunes)}, + {name: "truncates by rune", messages: []llm.Message{{Role: "user", Content: long, Authored: true}}, want: strings.Repeat("界", provisionalTitleRunes-1) + "…"}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -39,8 +39,8 @@ func TestProvisionalTitle(t *testing.T) { } func TestProvisionalTitlePersistsAcrossWritePaths(t *testing.T) { - input := strings.Repeat("界", 65) - want := strings.Repeat("界", 63) + "…" + input := strings.Repeat("界", provisionalTitleRunes+1) + want := strings.Repeat("界", provisionalTitleRunes-1) + "…" t.Run("Save", func(t *testing.T) { store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) diff --git a/internal/session/transcript_page_test.go b/internal/session/transcript_page_test.go index 461dfc064..dbe9e4402 100644 --- a/internal/session/transcript_page_test.go +++ b/internal/session/transcript_page_test.go @@ -6,8 +6,55 @@ import ( "path/filepath" "strings" "testing" + "time" + + "github.com/context-labs/whip/internal/llm" ) +func TestTranscriptPagePreservesAssistantTimestamp(t *testing.T) { + for _, name := range []string{"root", "child"} { + t.Run(name, func(t *testing.T) { + store, rootID, _ := newMailboxFixture(t) + agentID := rootID + if name == "child" { + agentID = "child" + } + stamp := time.Date(2025, 6, 1, 14, 30, 0, 123, time.UTC) + transcriptCommit(t, store, rootID, agentID, 1, []llm.Message{ + {Role: "assistant", Content: strings.Repeat("answer ", 1000), SentAt: &stamp}, + {Role: "assistant", Content: "legacy answer"}, + }) + for _, maxBytes := range []int{1024, 16384} { + page, err := store.ReadTranscriptPage(t.Context(), rootID, agentID, TranscriptReadOptions{ + ThroughSeq: -1, Limit: 2, MaxBytes: maxBytes, + }) + if err != nil || len(page.Messages) == 0 { + t.Fatalf("page: %+v, %v", page, err) + } + entry := page.Messages[0] + got := entry.SentAt + if maxBytes == 1024 { + if entry.Body == nil || entry.Message != nil || entry.Role != "assistant" { + t.Fatalf("expected stored body metadata: %+v", entry) + } + } else { + if entry.Message == nil || len(page.Messages) != 2 || page.Messages[1].Message.SentAt != nil { + t.Fatalf("expected inline and unstamped legacy messages: %+v", page) + } + got = entry.Message.SentAt + } + if entry.Seq != 1 || got == nil || !got.Equal(stamp) { + t.Fatalf("timestamp/provenance changed: %+v", entry) + } + encoded, err := json.Marshal(page) + if err != nil || !strings.Contains(string(encoded), stamp.Format(time.RFC3339Nano)) { + t.Fatalf("wire timestamp missing: %s, %v", encoded, err) + } + } + }) + } +} + func TestTranscriptPageBoundsRevisionAndRecent(t *testing.T) { store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) if err != nil { diff --git a/internal/session/transcript_test.go b/internal/session/transcript_test.go index 00d04b6ad..2216f2943 100644 --- a/internal/session/transcript_test.go +++ b/internal/session/transcript_test.go @@ -9,6 +9,7 @@ import ( "reflect" "strings" "testing" + "time" "github.com/context-labs/whip/internal/llm" ) @@ -61,6 +62,7 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( image := llm.ContentPart{Type: "image_url", W: 17, H: 29, ImageURL: &struct { URL string `json:"url"` }{URL: "data:image/png;base64,aW1hZ2U="}} + stamp := time.Date(2025, 6, 1, 14, 30, 0, 123, time.UTC) raw := []llm.Message{ {Role: "user", Content: "original instruction", Authored: true, Parts: []llm.ContentPart{{Type: "text", Text: "original instruction"}, image}}, {Role: "assistant", ToolCalls: []llm.ToolCall{{ID: "call-1", Type: "function", Function: struct { @@ -68,11 +70,11 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( Arguments string `json:"arguments"` }{Name: "exec", Arguments: `{"code":"print('precise args')"}`}}}}, {Role: "tool", ToolCallID: "call-1", Name: "exec", Content: strings.Repeat("large result Ω ", 200000)}, - {Role: "assistant", Content: "first answer"}, + {Role: "assistant", Content: "first answer", SentAt: &stamp}, {Role: "user", Content: "second instruction"}, {Role: "assistant", Content: "second answer"}, {Role: "user", Content: "third instruction"}, - {Role: "assistant", Content: "third answer"}, + {Role: "assistant", Content: "third answer", SentAt: &stamp}, } raw[1].Continuation = llm.ResponseContinuation{AccountID: "account", Model: "model", Items: `[{"type":"reasoning","encrypted_content":"opaque-model-state"}]`} transcriptCommit(t, store, rootID, agentID, 1, raw[:4]) @@ -137,6 +139,9 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( if err != nil || len(view) != 3 || !strings.Contains(view[0].Content, "second summary") || view[0].RawSequence != 6 || view[1].RawSequence != 7 || view[2].Content != "third answer" { t.Fatalf("derived view = %+v, %v", view, err) } + if view[0].SentAt != nil || view[1].SentAt != nil || view[2].SentAt == nil || !view[2].SentAt.Equal(stamp) { + t.Fatalf("compaction/restoration changed timestamps: %+v", view) + } }) } } diff --git a/internal/tui/client_control_render.go b/internal/tui/client_control_render.go index be671cba0..fadc262c5 100644 --- a/internal/tui/client_control_render.go +++ b/internal/tui/client_control_render.go @@ -33,7 +33,7 @@ func renderRuntimeControl(operation, output string) (string, bool, error) { return "", true, err } if value.BuiltinDefault { - return "automatic compaction restored to built-in defaults", true, nil + return "compaction model: Automatic (this conversation’s model and provider)", true, nil } return "compaction model: " + strings.TrimSpace(value.Model+" "+value.Provider), true, nil case "history.compact.retry": diff --git a/internal/tui/client_control_render_test.go b/internal/tui/client_control_render_test.go new file mode 100644 index 000000000..5f1cd7439 --- /dev/null +++ b/internal/tui/client_control_render_test.go @@ -0,0 +1,39 @@ +package tui + +import ( + "encoding/json" + "testing" + + "github.com/context-labs/whip/internal/protocol" +) + +func TestRenderCompactionSettings(t *testing.T) { + t.Parallel() + for _, test := range []struct { + name string + settings protocol.CompactionSettingsResult + want string + }{ + { + name: "automatic", + settings: protocol.CompactionSettingsResult{BuiltinDefault: true}, + want: "compaction model: Automatic (this conversation’s model and provider)", + }, + { + name: "custom former default", + settings: protocol.CompactionSettingsResult{Model: "deepseek-v4-flash-0731", Provider: "inference-net"}, + want: "compaction model: deepseek-v4-flash-0731 inference-net", + }, + } { + t.Run(test.name, func(t *testing.T) { + output, err := json.Marshal(test.settings) + if err != nil { + t.Fatal(err) + } + text, handled, err := renderRuntimeControl("compaction.configure", string(output)) + if err != nil || !handled || text != test.want { + t.Fatalf("render = %q %t %v, want %q", text, handled, err, test.want) + } + }) + } +} diff --git a/packages/app/src/chat-activity-rows.ts b/packages/app/src/chat-activity-rows.ts index e18a41d5d..7da8a3276 100644 --- a/packages/app/src/chat-activity-rows.ts +++ b/packages/app/src/chat-activity-rows.ts @@ -22,38 +22,58 @@ export const activityItems = (group: ActivityGroup): readonly ActivityItem[] => export const isActivityGroup = (row: TimelineRow): row is ActivityGroup => 'cells' in row; export const executionActive = (cell: ExecutionCell) => cell.status === 'running' || cell.status === 'writing'; -/** One footer for a response to an authored input. Internal deliveries and tool - * steps remain within that response; queued input does not finish active work. - * This is a view of retained prose, not a second turn/event store. +export interface ResponseActions { text: string; label: string; sentAt?: string; endpoint?: number } + +/** One footer per response, derived from retained source rows before Markdown + * splits. Internal deliveries and tool results belong to the response; queued + * input does not finish active work. Missing raw boundaries never permit edits. */ -export function responseCopies(rows: readonly ConversationActivityRow[], active: boolean, hasEarlier = false): ReadonlyMap<string, { text: string; label: string }> { - const copies = new Map<string, { text: string; label: string }>(); +export function responseCopies(rows: readonly ConversationActivityRow[], active: boolean, hasEarlier = false, throughSeq?: number): ReadonlyMap<string, ResponseActions> { + const copies = new Map<string, ResponseActions>(); let prose: string[] = []; let last: string | undefined; + let assistant = false; + let assistantSeq = -1; + let sentAt: string | undefined; let incomplete = hasEarlier; + let uncertain = hasEarlier; + let seqs = new Set<number>(); let bytes = 0; - const finish = () => { - if (last && prose.length) copies.set(last, { text: prose.join('\n\n'), label: incomplete ? 'Copy visible response' : 'Copy response' }); - prose = []; - last = undefined; - bytes = 0; - incomplete = false; + const finish = (nextSeq?: number) => { + if (last && assistant) { + const ordered = [...seqs].sort((a, b) => a - b); + const end = ordered.at(-1); + const contiguous = ordered.every((seq, index) => index === 0 || seq === ordered[index - 1]! + 1); + const endpoint = !uncertain && contiguous && end !== undefined && nextSeq === end + 1 ? end : undefined; + copies.set(last, { text: prose.join('\n\n'), label: incomplete ? 'Copy visible response' : 'Copy response', + ...(sentAt && Number.isFinite(new Date(sentAt).getTime()) ? { sentAt } : {}), ...(endpoint !== undefined ? { endpoint } : {}) }); + } + prose = []; last = undefined; assistant = false; assistantSeq = -1; sentAt = undefined; + bytes = 0; incomplete = false; uncertain = false; seqs = new Set(); }; for (const row of rows) { if (row.queued) continue; - if (row.historyGap) { incomplete = true; finish(); incomplete = true; continue; } - if (row.role === 'user') { finish(); continue; } - last = row.id; + if (row.historyGap) { incomplete = true; uncertain = true; finish(); incomplete = true; uncertain = true; continue; } + if (row.role === 'user') finish(row.seq); + else last = row.id; + if (row.live || row.historyUncertain || row.seq === undefined) uncertain = true; + for (const seq of [row.seq, ...(row.memberSeqs ?? [])]) { + if (seq === undefined || !Number.isSafeInteger(seq) || seq < 1 || seq >= Number.MAX_SAFE_INTEGER) uncertain = true; + else seqs.add(seq); + } + const recorded = row.assistantSeq ?? ((row.sourceRole ?? row.role) === 'assistant' ? row.seq : undefined); + if (recorded !== undefined && recorded >= assistantSeq) { assistantSeq = recorded; sentAt = row.sentAt; } if (row.role !== 'assistant') continue; - if (row.body) incomplete = true; + if (row.body || row.truncated) incomplete = true; const source = row.copyText ?? row.text; + assistant ||= !!(source.trim() || row.text.trim() || row.images?.length || row.body); if (!source.trim()) continue; // Bound derived copy strings as well as the underlying SDK window. - if (bytes + source.length > 256 * 1024) { incomplete = true; continue; } - prose.push(source); - bytes += source.length; + const size = source.length + (prose.length ? 2 : 0); + if (bytes + size > 256 * 1024) { incomplete = true; continue; } + prose.push(source); bytes += size; } - if (!active) finish(); + if (!active) finish(throughSeq === undefined ? undefined : throughSeq + 1); return copies; } @@ -102,9 +122,12 @@ export function conversationActivityRows( const aliases = new Set([id, ...pending.map(item => item.id), ...members.flatMap(row => [row.id, ...(row.memberIds ?? [])])]); for (const group of overlaps) for (const alias of [group.id, ...group.memberIds]) if (aliases.size < 512) aliases.add(alias); const groupedCells = [...new Map(pending.flatMap(item => item.cell ? [[item.cell.id, item.cell] as const] : [])).values()]; + const assistant = members.filter(row => row.assistantSeq !== undefined).sort((a, b) => b.assistantSeq! - a.assistantSeq!)[0]; output.push({ id, role: 'activity', text: '', seq: members[0]?.seq, cells: groupedCells, items: pending, updates: pending.flatMap(item => item.kind === 'mailbox' && item.row ? [item.row] : []), - memberIds: [...aliases].slice(0, 512), memberSeqs: [...new Set(members.flatMap(row => row.seq === undefined ? [] : [row.seq]))], + memberIds: [...aliases].slice(0, 512), memberSeqs: [...new Set(members.flatMap(row => [...(row.seq === undefined ? [] : [row.seq]), ...(row.memberSeqs ?? [])]))], + historyUncertain: members.some(row => row.seq === undefined || row.historyUncertain), + ...(assistant ? { assistantSeq: assistant.assistantSeq, sentAt: assistant.sentAt } : {}), live: pending.some(item => item.cell ? executionActive(item.cell) : item.row?.live), turnId: members.find(row => row.turnId)?.turnId ?? groupedCells[0]?.turnId }); pending = []; members = []; }; diff --git a/packages/app/src/chat-activity.tsx b/packages/app/src/chat-activity.tsx index 791c1a55b..4de0db7c2 100644 --- a/packages/app/src/chat-activity.tsx +++ b/packages/app/src/chat-activity.tsx @@ -1,8 +1,8 @@ import { useContext, useEffect, useState } from 'react'; import type { DeepReadonly, ExecutionCell, ExecutionRow, SessionViewSnapshot } from '@whip/sdk/state'; import type { RootSnapshot } from '@whip/protocol'; -import { ActivityIndicator, Button, IconButton, Tooltip, useTheme } from '@whip/ui'; -import { Circle, Pause, Play, ShieldAlert } from 'lucide-react'; +import { ActivityIndicator, Button, Tooltip, useTheme } from '@whip/ui'; +import { Circle, ShieldAlert } from 'lucide-react'; import * as stylex from '@stylexjs/stylex'; import { surface, typography } from '@whip/ui/tokens.stylex'; import { cellActivityLabel, executionActive } from './chat-activity-rows'; @@ -98,7 +98,7 @@ export function agentStatus(agent: Agent, active: boolean, connected: boolean, { export function CurrentActivity({ status, connected, onDetails }: { status: ReturnType<typeof activityStatus>; connected: boolean; onDetails(): void; }) { - const { display, setDisplay } = useTheme(); + const { display } = useTheme(); return <div aria-label="Current activity" data-current-activity {...stylex.props(styles.statusRow)}> <Tooltip label={status.text}> <Button variant="ghost" size="sm" xstyle={styles.statusButton} aria-label={`Activity: ${status.text}`} onClick={onDetails}> @@ -107,10 +107,6 @@ export function CurrentActivity({ status, connected, onDetails }: { </Button> </Tooltip> {status.cell && <span {...stylex.props(styles.statusTime)}><ExecutionTime cell={status.cell} connected={connected} /></span>} - {status.active && <IconButton variant="ghost" size="sm" label={display.motion === 'reduce' ? 'Use system motion setting' : 'Pause activity animation'} - onClick={() => setDisplay({ motion: display.motion === 'reduce' ? 'system' : 'reduce' })}> - {display.motion === 'reduce' ? <Play size={12} /> : <Pause size={12} />} - </IconButton>} </div>; } diff --git a/packages/app/src/compaction-settings.tsx b/packages/app/src/compaction-settings.tsx new file mode 100644 index 000000000..e50e264cd --- /dev/null +++ b/packages/app/src/compaction-settings.tsx @@ -0,0 +1,100 @@ +import { useState } from 'react'; +import type { WhipClient } from '@whip/sdk'; +import type { ConfigurationUpdate, RuntimeConfiguration } from '@whip/protocol'; +import { Collapsible, Input, Select } from '@whip/ui'; +import * as stylex from '@stylexjs/stylex'; +import { CatalogModelPicker, useProviderCatalog } from './model-selection'; +import { SettingRow, settingsSection } from './settings/section-layout'; +import { layout } from './styles'; + +const styles = stylex.create({ summary: { minWidth: 0, overflowWrap: 'anywhere' } }); + +// Keep invalid input text in the draft; numeric zero is reserved for Automatic. +export type CompactionValues = Pick<RuntimeConfiguration, 'compact_model' | 'compact_provider'> & { compact_percent: number | string }; + +export function compactionError(value: CompactionValues, base: CompactionValues): string | undefined { + if (value.compact_percent === base.compact_percent || value.compact_percent === 0) return; + const percent = Number(value.compact_percent); + if (!Number.isInteger(percent) || percent < 10 || percent > 90) { + return 'Use a whole-number percentage from 10 to 90, or choose Automatic.'; + } +} + +/** Omit untouched overrides so saving another setting never rewrites legacy values. */ +export function compactionPatch(value: CompactionValues, base: CompactionValues): Pick<ConfigurationUpdate, 'compact_model' | 'compact_provider' | 'compact_percent'> { + return { + ...(value.compact_model !== base.compact_model || value.compact_provider !== base.compact_provider ? { + compact_model: value.compact_model.trim(), + compact_provider: value.compact_model.trim() ? value.compact_provider : '', + } : {}), + ...(value.compact_percent !== base.compact_percent ? { compact_percent: Number(value.compact_percent) } : {}), + }; +} + +/** Shared host-default draft controls; neither surface applies runtime changes here. */ +export function CompactionSettings({ client, value, base, disabled, onChange }: { + client: WhipClient; value: CompactionValues; base: CompactionValues; disabled: boolean; + onChange(value: CompactionValues): void; +}) { + const [advanced, setAdvanced] = useState(false); + const [choosingModel, setChoosingModel] = useState(false); + const customModel = !!value.compact_model.trim(); + const customTiming = value.compact_percent !== 0; + const catalog = useProviderCatalog(client, !disabled && advanced && (customModel || choosingModel)); + const result = catalog.data?.result; + // A custom override must select a known, connected route, not arbitrary provider text. + const connected = (provider: string) => result?.providers[provider]?.available === true; + const connectedCatalog = result && { + ...result, + models: Object.fromEntries(Object.entries(result.models).map(([name, model]) => + [name, { ...model, providers: model.providers?.filter(connected) ?? [] }])), + catalogs: Object.fromEntries(Object.entries(result.catalogs).filter(([provider]) => connected(provider))), + }; + const percent = Number(value.compact_percent); + const effectivePercent = percent === 0 ? 50 : Math.max(10, Math.min(90, percent)); + const error = compactionError(value, base); + const legacyPercent = value.compact_percent === base.compact_percent && percent !== 0 && percent !== effectivePercent; + return <> + <p {...stylex.props(layout.muted)}>Older active context is summarized. Full conversation history remains available.</p> + <SettingRow id="compact_model" label="Summary model"> + <span {...stylex.props(styles.summary)}>{customModel ? `Custom · ${value.compact_model} · ${value.compact_provider || 'provider resolved by host'}` : 'Automatic · conversation model and provider'}</span> + </SettingRow> + <SettingRow id="compact_percent" label="When to compact" + description={legacyPercent ? `Saved value: ${percent}%. The effective threshold is ${effectivePercent}%; saving other settings keeps the saved value.` : undefined}> + <span>{error ? 'Custom · choose 10–90%' : `${percent === 0 ? 'Automatic' : 'Custom'} · ${effectivePercent}%`}</span> + </SettingRow> + <Collapsible title="Advanced compaction settings" open={advanced} onOpenChange={setAdvanced}> + <div {...stylex.props(layout.column)}> + <SettingRow id="compact_model_mode" label="Summary model override" description="Use the conversation model, or choose a connected model and provider together."> + <Select label="Summary model mode" value={customModel || choosingModel ? 'custom' : 'automatic'} disabled={disabled} xstyle={settingsSection.control} + options={[{ value: 'automatic', label: 'Automatic' }, { value: 'custom', label: 'Custom' }]} + onValueChange={mode => { + setChoosingModel(mode === 'custom'); + if (mode === 'automatic') onChange({ ...value, compact_model: '', compact_provider: '' }); + }} /> + </SettingRow> + {(customModel || choosingModel) && <SettingRow id="compact_custom_model" label="Custom summary model" + description="If this route is unavailable, the conversation model is used instead. Saved overrides stay unchanged until you edit them."> + <CatalogModelPicker settings label="Custom summary model" model={value.compact_model} provider={customModel ? value.compact_provider : ''} + catalog={connectedCatalog} loading={catalog.isLoading} error={disabled ? undefined : catalog.error?.message} onRetry={() => void catalog.refetch()} + disabled={disabled} xstyle={settingsSection.control} + onChange={(model, provider) => { setChoosingModel(false); onChange({ ...value, compact_model: model, compact_provider: provider }); }} /> + </SettingRow>} + <SettingRow id="compact_timing" label="Compaction timing"> + <Select label="Compaction timing" value={customTiming ? 'custom' : 'automatic'} disabled={disabled} xstyle={settingsSection.control} + options={[{ value: 'automatic', label: 'Automatic · 50%' }, { value: 'custom', label: 'Custom' }]} + onValueChange={mode => onChange({ ...value, compact_percent: mode === 'automatic' ? 0 : 50 })} /> + </SettingRow> + {customTiming && <SettingRow id="compact_custom_percent" label="Context window percentage" description="Compact when active context reaches this share of the model’s context window. Choose 10–90%."> + <Input aria-label="Context window percentage" type="number" min={10} max={90} step={1} disabled={disabled} + aria-invalid={!!error} aria-describedby={error ? 'compact-percent-error' : undefined} xstyle={settingsSection.control} + value={value.compact_percent} onChange={event => { + const next = event.target.valueAsNumber; + onChange({ ...value, compact_percent: Number.isInteger(next) && next >= 10 && next <= 90 ? next : event.target.value }); + }} /> + </SettingRow>} + {error && <p id="compact-percent-error" role="alert">{error}</p>} + </div> + </Collapsible> + </>; +} diff --git a/packages/app/src/conversation-rows.ts b/packages/app/src/conversation-rows.ts index 990202b78..e407c8773 100644 --- a/packages/app/src/conversation-rows.ts +++ b/packages/app/src/conversation-rows.ts @@ -6,6 +6,8 @@ import { admittedText, inboxInputId, isChatInput, matchesInput, submittedInputId export interface TimelineRow { id: string; role: string; + /** Raw record role differs from display role for interrupted presentation text. */ + sourceRole?: string; text: string; label?: string; args?: string; @@ -13,6 +15,11 @@ export interface TimelineRow { deliveries?: number; body?: NonNullable<HistoryView['messages'][number]['body']>; seq?: number; + /** Canonical records folded into this display row (for example tool results). */ + memberSeqs?: readonly number[]; + historyUncertain?: boolean; + /** Assistant source identity survives rich parts and activity grouping. */ + assistantSeq?: number; images?: ImagePart[]; designContext?: DeepReadonly<DesignContext> | null; designEvidence?: { context: DeepReadonly<DesignContext>; rawText: string; image?: ImagePart }; @@ -103,14 +110,18 @@ export function timelineRows( // screenshots). Only authored input belongs in the desktop/web user bubble. const sourceRole = message?.role ?? entry.role ?? 'notice'; const role = rich && sourceRole === 'user' && !(message?.authored ?? entry.authored) ? 'internal' : sourceRole; + const sentAt = message?.sent_at ?? entry.sent_at ?? undefined; + const assistant = { sourceRole, ...(sourceRole === 'assistant' ? { assistantSeq: entry.seq, sentAt } : {}) }; const metadata = message?.presentation ?? entry.presentation; const orderedParts = rich && metadata?.version === 1 ? metadata.parts ?? [] : []; const resultPart = orderedParts.find(part => part.kind === 'result' && part.call_id); if (!message && resultPart && calls.has(resultPart.call_id!) && (!calls.get(resultPart.call_id!)!.turnId || calls.get(resultPart.call_id!)!.turnId === metadata!.turn_id)) { - calls.get(resultPart.call_id!)!.body = entry.body ?? undefined; + const call = calls.get(resultPart.call_id!)!; + call.body = entry.body ?? undefined; + call.memberSeqs = [...(call.memberSeqs ?? []), entry.seq]; // Pending presentation (e.g. interrupted reasoning) still follows this result. for (const part of orderedParts) if (part.kind === 'reasoning' || (part.kind === 'text' && part.text)) - rows.push({ id: `part:${part.id}`, partId: part.id, seq: entry.seq, turnId: metadata!.turn_id, role: part.kind === 'text' ? 'assistant' : 'reasoning', text: part.text ?? '', body: entry.body ?? undefined, truncated: !!part.omitted }); + rows.push({ id: `part:${part.id}`, partId: part.id, seq: entry.seq, ...assistant, turnId: metadata!.turn_id, role: part.kind === 'text' ? 'assistant' : 'reasoning', text: part.text ?? '', body: entry.body ?? undefined, truncated: !!part.omitted }); continue; } const detailed: TimelineRow[] = []; @@ -118,7 +129,7 @@ export function timelineRows( const prose = messagePresentation(message?.content).text; const encoded = new TextEncoder().encode(prose); for (const part of orderedParts) { - const base = { id: `part:${part.id}`, partId: part.id, seq: entry.seq, turnId: metadata!.turn_id, memberIds: [id], truncated: !!(metadata!.omitted || part.omitted) }; + const base = { id: `part:${part.id}`, partId: part.id, seq: entry.seq, ...assistant, turnId: metadata!.turn_id, memberIds: [id], truncated: !!(metadata!.omitted || part.omitted) }; if (part.kind === 'reasoning') detailed.push({ ...base, role: 'reasoning', text: part.text ?? '', body: entry.body ?? undefined }); else if (part.kind === 'text' && part.text) detailed.push({ ...base, role: 'assistant', text: part.text, copyText: part.text, truncated: true }); else if (part.kind === 'text' && message?.role === 'assistant' && !metadata!.omitted) { @@ -132,10 +143,10 @@ export function timelineRows( } } if (message?.role === 'assistant' || !message) { - if (metadata!.omitted && prose) detailed.push({ id, seq: entry.seq, role: 'assistant', text: prose }); - if (entry.body && !detailed.some(row => row.body)) detailed.push({ id, seq: entry.seq, role, text: '', body: entry.body ?? undefined }); + if (metadata!.omitted && prose) detailed.push({ id, seq: entry.seq, ...assistant, role: 'assistant', text: prose }); + if (entry.body && !detailed.some(row => row.body)) detailed.push({ id, seq: entry.seq, ...assistant, role, text: '', body: entry.body ?? undefined }); const images = messagePresentation(message?.content).images; - if (images.length) detailed.push({ id: `${id}:images`, seq: entry.seq, role: 'assistant', text: '', images }); + if (images.length) detailed.push({ id: `${id}:images`, seq: entry.seq, ...assistant, role: 'assistant', text: '', images }); let copied = false; for (const row of detailed) if (row.role === 'assistant' && row.copyText === undefined) { row.copyText = copied ? '' : prose; copied = true; } rows.push(...detailed); @@ -148,7 +159,8 @@ export function timelineRows( seq: entry.seq, role, text: '', - sentAt: entry.sent_at ?? undefined, + sentAt, + ...assistant, ...(entry.body ? { body: entry.body ?? undefined } : {}), }); continue; @@ -165,6 +177,7 @@ export function timelineRows( previous.text === parts.text ) { previous.deliveries = (previous.deliveries ?? 1) + 1; + previous.memberSeqs = [...(previous.memberSeqs ?? []), entry.seq]; continue; } if ( @@ -173,6 +186,8 @@ export function timelineRows( calls.has(message.tool_call_id) && (!rich || !metadata?.turn_id || !calls.get(message.tool_call_id)!.turnId || calls.get(message.tool_call_id)!.turnId === metadata.turn_id) ) { + const call = calls.get(message.tool_call_id)!; + call.memberSeqs = [...(call.memberSeqs ?? []), entry.seq]; calls.get(message.tool_call_id)!.text = parts.text; calls.get(message.tool_call_id)!.images = parts.images; if (entry.body) calls.get(message.tool_call_id)!.body = entry.body; @@ -187,7 +202,8 @@ export function timelineRows( text: parts.text, images: parts.images, ...(parts.designEvidence ? { designEvidence: parts.designEvidence } : {}), - sentAt: message.sent_at ?? entry.sent_at ?? undefined, + sentAt, + ...assistant, ...(message.role === 'tool' ? { label: message.name || 'Tool output' } : {}), @@ -198,6 +214,7 @@ export function timelineRows( const row: TimelineRow = { id: `${id}:${call.id}`, seq: entry.seq, + ...assistant, role: 'tool', toolName: call.function.name, callId: call.id, diff --git a/packages/app/src/conversation.tsx b/packages/app/src/conversation.tsx index 025a95a9f..54ae8560d 100644 --- a/packages/app/src/conversation.tsx +++ b/packages/app/src/conversation.tsx @@ -146,7 +146,10 @@ export function SessionContent({ action: 'fork' | 'rewind'; cut: number; revision: string; + response?: { endpoint: number; runtimeId: string; rootId: string }; }>(); + const historyBusy = useRef(false); + const [historyPending, setHistoryPending] = useState(false); const [stored, setStored] = useState<{ title: string; text?: string; @@ -232,6 +235,7 @@ export function SessionContent({ ) : [], [kind, history, presentation, inbox, localInputs, deliveries, queueEnabled]); const executions = useMemo(() => executionRows(state, agentId), [state, agentId]); const activeTurn = root?.active_turns[agentId]; + const rootBusy = !!root?.active_turns[session.rootId] || root?.agents?.some(item => item.id === session.rootId && item.status === 'running'); const previousGroups = useRef<readonly ActivityGroup[]>([]); const activityRows = useMemo(() => conversationActivityRows(rows, executions, previousGroups.current, activeTurn), [rows, executions, activeTurn]); useLayoutEffect(() => { previousGroups.current = activityRows.filter(isActivityGroup).slice(-128); }, [activityRows]); @@ -341,6 +345,8 @@ export function SessionContent({ bookmarkKey={`${expectedRuntimeId}:${viewId ?? session.rootId}:${agentId}`} historyRevision={history?.revision} historyCursor={history?.nextSeq} + historyThroughSeq={history?.throughSeq} + rewindDisabled={rootBusy} historyReady={!!history && !history.loading} canLoadOlder={connected} loadingHistory={history?.loading} @@ -351,6 +357,13 @@ export function SessionContent({ latestMissing={history?.latestMissing} readBody={(row) => void readBody(row)} messageScope={{ client: session.client, rootId: session.rootId, agentId }} + responseHistoryAction={agentId === session.rootId && connected && root && history?.revision === root.history_revision + ? (endpoint, action) => { + if (!Number.isSafeInteger(endpoint) || endpoint < 1 || endpoint >= Number.MAX_SAFE_INTEGER) return; + if (action === 'rewind' && (rootBusy || endpoint >= history.throughSeq)) return; + setHistoryAction({ action, cut: action === 'rewind' ? endpoint + 1 : endpoint, revision: history.revision, + response: { endpoint, runtimeId: expectedRuntimeId, rootId: session.rootId } }); + } : undefined} historyAction={ agentId === session.rootId && connected && root ? (row, action) => { @@ -512,25 +525,39 @@ export function SessionContent({ if (!open) setHistoryAction(undefined); }} title={ - historyAction?.action === 'rewind' - ? 'Rewind before this message?' - : 'Fork before this message?' + historyAction?.response + ? historyAction.action === 'rewind' ? 'Rewind to here?' : 'Fork from here?' + : historyAction?.action === 'rewind' ? 'Rewind before this message?' : 'Fork before this message?' } description={ - historyAction?.action === 'rewind' + historyAction?.response + ? historyAction.action === 'rewind' + ? 'Keep this response and remove only later conversation. Tracked file changes may be restored. The daemon rejects this action if history has changed since you selected it.' + : 'Create a separate session including this response. The current session continues independently.' + : historyAction?.action === 'rewind' ? 'Later conversation will be removed and tracked file changes may be restored. The daemon rejects this action if history has changed since you selected it.' : 'Create a separate session with the earlier conversation. The current session continues independently.' } footer={ <Button variant={historyAction?.action === 'rewind' ? 'danger' : 'primary'} - disabled={!connected || !historyAction} + disabled={!connected || !historyAction || historyPending || (!!historyAction.response && historyAction.action === 'rewind' && rootBusy)} onClick={async () => { - if (!historyAction) return; + if (!historyAction || !connected || historyBusy.current) return; if (historyAction.action === 'fork' && !canCreateTab()) return; const location = navigationRevision.current; setActionError(undefined); + historyBusy.current = true; setHistoryPending(true); try { + if (historyAction.response) { + const target = historyAction.response; + if (agentId !== session.rootId || target.rootId !== session.rootId || target.runtimeId !== expectedRuntimeId || currentRuntime !== target.runtimeId) + throw new Error('This response belongs to a different conversation or host. Select it again.'); + if (root?.history_revision !== historyAction.revision || history?.revision !== historyAction.revision) + throw new Error('History has changed since you selected this response. Select it again.'); + if (historyAction.action === 'rewind' && (rootBusy || target.endpoint >= history.throughSeq)) + throw new Error('Rewind is unavailable while work is running or there is no later conversation.'); + } if (historyAction.action === 'rewind') await runtime.run( session.history.rewind( @@ -552,6 +579,7 @@ export function SessionContent({ } if (stillHere(location)) setHistoryAction(undefined); } catch (error) { if (stillHere(location)) setActionError(error); } + finally { historyBusy.current = false; if (mounted.current) setHistoryPending(false); } }} > Confirm {historyAction?.action} diff --git a/packages/app/src/details/session-controls.tsx b/packages/app/src/details/session-controls.tsx index be43aa1bb..905147f94 100644 --- a/packages/app/src/details/session-controls.tsx +++ b/packages/app/src/details/session-controls.tsx @@ -6,6 +6,7 @@ import * as stylex from '@stylexjs/stylex'; import { useRuntime } from '../context'; import { layout } from '../styles'; import { ModelSelection } from '../model-selection'; +import { CompactionSettings, compactionError, compactionPatch, type CompactionValues } from '../compaction-settings'; import { describeRule, splitGlobalRule } from '../permission-scope'; import { Action, @@ -390,15 +391,18 @@ export function Compaction(props: InspectorProps) { enabled: props.connected, gcTime: 0, }); - const [draft, setDraft] = useState<{ revision: string; model: string; provider: string }>(); - const model = draft?.model ?? configuration.data?.compact_model ?? ''; - const provider = draft?.provider ?? configuration.data?.compact_provider ?? ''; - const edit = (field: 'model' | 'provider', value: string) => { + const [draft, setDraft] = useState<{ revision: string; base: CompactionValues; value: CompactionValues }>(); + const [applying, setApplying] = useState(false); + const defaults: CompactionValues = { + compact_model: configuration.data?.compact_model ?? '', + compact_provider: configuration.data?.compact_provider ?? '', + compact_percent: configuration.data?.compact_percent ?? 0, + }; + const value = draft?.value ?? defaults; + const base = draft?.base ?? defaults; + const edit = (next: CompactionValues) => { if (!configuration.data) return; - setDraft({ - ...(draft ?? { revision: configuration.data.revision, model, provider }), - [field]: value, - }); + setDraft({ revision: draft?.revision ?? configuration.data.revision, base, value: next }); }; const [offset, setOffset] = useState(0); const idle = !Object.keys(props.root.active_turns ?? {}).length; @@ -407,7 +411,7 @@ export function Compaction(props: InspectorProps) { <> <Section title="Compaction" - description="Compaction reduces model context while retaining raw transcript history. It does not undo files." + description="These are shared host defaults, not a live session override. Applying them saves the host settings and reloads this session only while it is idle." > <Action disabled={!props.connected || !idle} @@ -415,37 +419,25 @@ export function Compaction(props: InspectorProps) { > Compact now </Action> - <Field - label="Compaction model" - description="Blank restores WHIP’s built-in compaction model. This updates shared host defaults and reloads this idle session." - > - <Input - value={model} - disabled={!configuration.data} - onChange={(event) => edit('model', event.target.value)} - /> - </Field> - <Field label="Compaction provider"> - <Input - value={provider} - disabled={!configuration.data} - onChange={(event) => edit('provider', event.target.value)} - /> - </Field> + {(configuration.data || draft) && <CompactionSettings client={props.view.session.client} value={value} base={base} + disabled={!props.connected || applying} onChange={edit} />} <Action - disabled={!props.connected || !idle || !configuration.data} + disabled={!props.connected || !idle || !configuration.data || applying || !!compactionError(value, base)} run={async () => { - await props.view.session.client.configuration.update({ - revision: draft?.revision ?? configuration.data!.revision, - compact_model: model, - compact_provider: model ? provider : '', - }); - await runtime.run( - props.view.session.command('session.reload', {}), - 'Reload compaction settings', - ); - setDraft(undefined); - await configuration.refetch(); + setApplying(true); + try { + await props.view.session.client.configuration.update({ + revision: draft?.revision ?? configuration.data!.revision, + ...compactionPatch(value, base), + }); + await runtime.run( + props.view.session.command('session.reload', {}), + 'Reload compaction settings', + ); + setDraft(undefined); + await configuration.refetch(); + void runtime.queries.invalidateQueries({ queryKey: ['runtime-configuration', props.view.session.client.getSnapshot().info?.runtime_id] }); + } finally { setApplying(false); } }} > Apply compaction defaults @@ -459,7 +451,7 @@ export function Compaction(props: InspectorProps) { )} <Button variant="ghost" - disabled={!props.connected} + disabled={!props.connected || applying} onClick={() => { setDraft(undefined); void configuration.refetch(); diff --git a/packages/app/src/session-search-dialog.tsx b/packages/app/src/session-search-dialog.tsx index e9e944fd7..3c3e4f91b 100644 --- a/packages/app/src/session-search-dialog.tsx +++ b/packages/app/src/session-search-dialog.tsx @@ -4,7 +4,7 @@ import { useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } fro import { Link } from '@tanstack/react-router'; import { useQueries } from '@tanstack/react-query'; import type { SessionCatalogPage } from '@whip/protocol'; -import { Button, ContextMenu, Dialog, IconButton, Input, Menu, Select, type DialogProps } from '@whip/ui'; +import { Button, ContextMenu, Dialog, IconButton, Input, Menu, type DialogProps } from '@whip/ui'; import { Code2, CornerDownLeft, MoreHorizontal, Search } from 'lucide-react'; import * as stylex from '@stylexjs/stylex'; import { colors, scale, surface } from '@whip/ui/tokens.stylex'; @@ -24,7 +24,6 @@ function SearchDialog({ onOpenChange, finalFocus }: Props) { const [actionError, setActionError] = useState<{ owner: string; error: unknown }>(); const { hosts } = useAppState(); useSessionTabs(); - const [filter, setFilter] = useState(''); const [search, setSearch] = useState(''); const [term, setTerm] = useState(''); const [cursors, setCursors] = useState<Record<string, SessionCatalogPage['next_cursor']>>({}); @@ -32,7 +31,8 @@ function SearchDialog({ onOpenChange, finalFocus }: Props) { const input = useRef<HTMLInputElement>(null); const results = useRef<HTMLDivElement>(null); const resultId = useId(); - const visibleHosts = useMemo(() => hosts.filter(host => !filter || host.id === filter), [hosts, filter]); + // ponytail: search always spans every host; no host filter. + const visibleHosts = hosts; // Observe catalog revisions to refresh search without a second list poller. const catalogs = useMemo(() => { let snapshot = visibleHosts.map(host => host.list?.getSnapshot()); @@ -111,8 +111,7 @@ function SearchDialog({ onOpenChange, finalFocus }: Props) { event.preventDefault(); results.current?.querySelector<HTMLAnchorElement>(`[data-search-index="${current}"] a`)?.click(); } }} /> - </div>{hosts.length > 1 && <Select label="Search host" value={filter} options={[{ value: '', label: 'All hosts' }, ...hosts.map(host => ({ value: host.id, label: host.name }))]} - onValueChange={value => { setFilter(value); setSelected(undefined); }} />}</div>}> + </div></div>}> <div ref={results} id={resultId} {...stylex.props(styles.results)} aria-label="Session search results" aria-busy={loading}> {actionError && <ErrorNotice type="action" owner={actionError.owner} error={actionError.error} title="Could not open session" onDismiss={() => setActionError(undefined)} />} {groups.map(group => { @@ -150,7 +149,6 @@ function SearchDialog({ onOpenChange, finalFocus }: Props) { {cursors[runtimeId] && <Button variant="ghost" onClick={() => cursor(runtimeId, undefined)}>First results{hosts.length > 1 ? ` on ${host.name}` : ''}</Button>} </section>; })} - {!groups.length && <p role="status" {...stylex.props(styles.notice)}>No hosts selected.</p>} </div> <span role="status" {...stylex.props(layout.srOnly)}>{active ? `${active.session.title || 'Untitled session'} on ${active.host.name}, result ${current + 1} of ${items.length}` : ''}</span> </Dialog>; diff --git a/packages/app/src/session-sidebar.stylex.ts b/packages/app/src/session-sidebar.stylex.ts index 9f87726c6..da8d2d67e 100644 --- a/packages/app/src/session-sidebar.stylex.ts +++ b/packages/app/src/session-sidebar.stylex.ts @@ -16,10 +16,21 @@ export const styles = stylex.create({ }, scrollEdgeVisible: { opacity: 1 }, scrollContent: { display: 'flex', flexDirection: 'column', minHeight: '100%' }, - hosts: { display: 'flex', flexDirection: 'column', flexShrink: 0, gap: 8 }, - host: { display: 'flex', flexDirection: 'column' }, - collapsedHost: { flex: '0 0 auto', minHeight: 0 }, - hostHeading: { flexShrink: 0, color: colors.foreground }, + projects: { display: 'flex', flexDirection: 'column', flexShrink: 0 }, + feedback: { paddingInline: 8, fontSize: typography.size12, color: colors.muted }, + hostMetadata: { flexShrink: 1, maxWidth: '45%', fontSize: typography.size11, paddingInline: 4, gap: 4, color: surface.secondaryText }, + connectionLabel: { flexShrink: 0 }, + statusDot: { flexShrink: 0 }, + connected: { color: colors.success }, + hostDetails: { display: 'flex', flexDirection: 'column', width: 300, maxWidth: 'calc(100vw - 24px)', padding: 4, borderWidth: 1, borderStyle: 'solid', borderColor: surface.quietBorder, overflowWrap: 'anywhere' }, + hostHeading: { display: 'flex', flexDirection: 'column', gap: 2, padding: 8 }, + hostHeadingRow: { display: 'flex', alignItems: 'center', gap: 8 }, + hostStatus: { display: 'flex', alignItems: 'center', flexShrink: 0, gap: 4, fontSize: typography.size11, fontWeight: 400, color: surface.secondaryText }, + hostConnection: { paddingInlineStart: 22, fontSize: typography.size12, fontWeight: 400, color: surface.secondaryText }, + hostPath: { display: 'flex', alignItems: 'start', gap: 8, paddingInline: 8, paddingBlock: 4, fontSize: typography.size12, lineHeight: 1.5, color: surface.secondaryText }, + detailIcon: { flexShrink: 0, marginTop: 2, color: surface.secondaryText }, + hostError: { paddingInline: 8, paddingBlock: 4, fontSize: typography.size12, color: surface.secondaryText }, + hostAction: { justifyContent: 'flex-start', gap: 8, paddingInline: 8, fontWeight: 400, color: surface.secondaryText }, brandRow: { minHeight: 40, display: 'flex', alignItems: 'center', flexShrink: 0 }, // Inset window chrome: the brand row is an empty window drag strip whose // height matches the tab strip so the traffic lights sit centered in both; @@ -34,14 +45,14 @@ export const styles = stylex.create({ // The wordmark link is a plain graphic home link — no destination row's // hover container, just the mark itself. wordmarkLink: { display: 'flex', alignItems: 'center', paddingInline: 8, borderRadius: 6, color: colors.foreground }, - destinations: { display: 'flex', flexDirection: 'column', flexShrink: 0, marginBottom: 12 }, + destinations: { display: 'flex', flexDirection: 'column', flexShrink: 0, gap: 1, marginBottom: 12 }, destination: { display: 'flex', alignItems: 'center', gap: 8, minWidth: 0, minHeight: { default: 28, [scale.touch]: 44 }, paddingBlock: 0, paddingInline: 8, borderWidth: 0, borderRadius: 6, font: 'inherit', fontSize: typography.size13, lineHeight: `calc(${typography.size13} * 18 / 13)`, textAlign: 'left', textDecoration: 'none', cursor: 'pointer', color: surface.secondaryText, backgroundColor: { default: 'transparent', ':hover': colors.hover } }, moreButton: { minHeight: 0, paddingInline: 10, color: colors.muted }, primaryDestination: { color: colors.foreground }, footer: { minHeight: 48, display: 'flex', alignItems: 'center', flexShrink: 0, borderTopWidth: 1, borderTopStyle: 'solid', borderTopColor: surface.quietBorder, marginTop: 'auto', paddingBlock: 8 }, list: { overflowAnchor: 'none', overscrollBehaviorY: 'contain', scrollbarWidth: 'thin', marginInline: -8, marginBottom: -8, paddingInline: 8, paddingBottom: 8 }, group: { display: 'flex', alignItems: 'end', paddingBottom: 2, gap: 2 }, - groupButton: { fontSize: typography.size12, gap: 5, paddingInline: 4, backgroundColor: { default: 'transparent', ':hover': 'transparent' } }, + groupButton: { height: { default: 28, [scale.touch]: 44 }, fontSize: typography.size12, fontWeight: 500, gap: 6, paddingInline: 8, backgroundColor: { default: 'transparent', ':hover': 'transparent' } }, icon: { minHeight: { default: 28, [scale.touch]: 44 }, height: { default: 28, [scale.touch]: 44 }, width: { default: 28, [scale.touch]: 44 }, minWidth: { default: 28, [scale.touch]: 44 }, padding: 0, justifyContent: 'center', flexShrink: 0, color: surface.secondaryText }, sessionRow: { display: 'flex', alignItems: 'center', height: '100%', borderRadius: 6, color: surface.secondaryText, backgroundColor: { default: 'transparent', ':hover': colors.element } }, selected: { backgroundColor: { default: colors.hover, ':hover': colors.hover }, color: colors.foreground }, diff --git a/packages/app/src/session-sidebar.tsx b/packages/app/src/session-sidebar.tsx index f0071761e..2eddac82d 100644 --- a/packages/app/src/session-sidebar.tsx +++ b/packages/app/src/session-sidebar.tsx @@ -1,27 +1,26 @@ import { WorkspaceExternalSource } from '@whip/ui/workspace-tabs'; import { ErrorNotice } from './error-feedback'; -import { useEffect, useLayoutEffect, useMemo, useRef, useState, type Dispatch, type SetStateAction, type ReactNode, type RefObject } from 'react'; +import { useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, type Dispatch, type SetStateAction, type ReactNode, type RefObject } from 'react'; import { Link, useLocation, useNavigate } from '@tanstack/react-router'; import { useVirtualizer } from '@tanstack/react-virtual'; -import { useWhipConnection, useSessionListView } from '@whip/sdk/react'; -import type { WhipClient } from '@whip/sdk'; -import type { DeepReadonly, SessionListView } from '@whip/sdk/state'; -import type { SessionCatalogPage } from '@whip/protocol'; -import { useQuery } from '@tanstack/react-query'; -import { Button, IconButton, Menu, ContextMenu, Spinner, WhipcodeWordmark } from '@whip/ui'; -import { Plus, Search, Settings2, Plug, ArrowUpRight, MoreHorizontal, ChevronRight, ChevronDown, Circle, Pin, MessageSquare, MessageSquareWarning, Archive } from 'lucide-react'; +import type { DeepReadonly, SessionListSnapshot } from '@whip/sdk/state'; +import type { SessionNavigationSummary } from './session-status'; +import { useQueries } from '@tanstack/react-query'; +import { Button, IconButton, Menu, ContextMenu, Spinner, WhipcodeWordmark, Tooltip, Popover } from '@whip/ui'; +import { Plus, Search, Settings2, Plug, ArrowUpRight, MoreHorizontal, ChevronRight, ChevronDown, Circle, Pin, MessageSquare, MessageSquareWarning, Archive, Folder, Globe, RotateCw } from 'lucide-react'; import * as stylex from '@stylexjs/stylex'; import { styles, sessionMarker, directoryMarker } from './session-sidebar.stylex'; import { layout } from './styles'; import { useAppState, useRuntime, useSessionTabs } from './context'; import { sessionBusy, sessionNeedsInput } from './session-status'; -import { sidebarRows, setDirectoryCollapsed, defaultDirectorySessionLimit, type SidebarState } from './sidebar-state'; +import { mixedSidebarRows, sidebarRowKey, setDirectoryCollapsed, defaultDirectorySessionLimit, type SidebarState, type HostSidebarRow } from './sidebar-state'; import { openNewChat, sessionDestination } from './session-tab-routing'; import type { HostConnection } from './hosts'; import { useSessionActions } from './session-actions'; import { sessionSearch } from './session-tabs'; const noCollapsedDirectories: readonly string[] = []; +const sidebarRowGap = 1; interface SidebarProps { headerAction?: ReactNode; @@ -49,33 +48,129 @@ export function SessionSidebar(props: SidebarProps) { <button onClick={props.onSearch} {...stylex.props(styles.destination, styles.primaryDestination)}><Search size={16} />Search sessions</button> <Link id="whip-settings-link" to="/settings" search={{ section: "general" }} onClick={props.onNavigate} {...stylex.props(styles.destination, styles.primaryDestination)}><Settings2 size={16} />Settings</Link> </nav> - <div {...stylex.props(styles.hosts)}> - {app.hosts.map(host => <HostSection key={host.id} host={host} showHeading={app.hosts.length > 1} {...props} scroll={scroll} content={content} />)} - </div> + <section aria-label="Projects" {...stylex.props(styles.projects)}> + <SessionRows hosts={app.hosts} {...props} scroll={scroll} content={content} /> + </section> <SidebarFooter onConnect={props.onConnect} /> </div> </div> </>; } type SidebarScroll = { scroll: RefObject<HTMLDivElement | null>; content: RefObject<HTMLDivElement | null> }; -function HostSection({ host, showHeading, ...props }: SidebarProps & SidebarScroll & { host: HostConnection; showHeading: boolean }) { + +function useSidebarActivity(hosts: readonly HostConnection[], rows: readonly HostSidebarRow[]) { + const runtime = useRuntime(); + const [visible, setVisible] = useState(() => document.visibilityState !== 'hidden'); + useEffect(() => { + const change = () => setVisible(document.visibilityState !== 'hidden'); + document.addEventListener('visibilitychange', change); + return () => document.removeEventListener('visibilitychange', change); + }, []); + // Canonicalize the visible set so virtualizer renders don't restart subscriptions. + const selection = JSON.stringify(hosts.flatMap(host => { + const ids = rows.flatMap(row => row.kind === 'session' && row.runtimeId === host.runtimeId ? [row.session.id] : []).sort(); + return ids.length && host.client && host.runtimeId ? [[host.runtimeId, ids]] : []; + })); + const targets = useMemo(() => (JSON.parse(selection) as [string, string[]][]).map(([runtimeId, ids]) => { + const host = hosts.find(host => host.runtimeId === runtimeId)!; + return { runtimeId, ids, client: host.client!, enabled: visible && host.state === 'connected' + && !!host.client!.getSnapshot().info?.negotiated_capabilities?.includes('session_summaries') }; + }), [hosts, selection, visible]); + const summaries = useQueries({ queries: targets.map(({ runtimeId, ids, client, enabled }) => ({ + queryKey: ['session-sidebar-summaries', runtimeId, ids], + queryFn: async ({ signal }: { signal: AbortSignal }) => { + const items: SessionNavigationSummary[] = []; + for (let offset = 0; offset < ids.length; offset += 32) { + const page = await client.sessions.summaries(ids.slice(offset, offset + 32), { signal }); + items.push(...page.items); + } + return { items }; + }, + enabled, + refetchInterval: enabled ? 2000 : false as const, + refetchIntervalInBackground: false, + refetchOnWindowFocus: true, + staleTime: 0, + gcTime: 0, + })) }); + useEffect(() => { + const releases = targets.filter(target => target.enabled).map(({ client, runtimeId, ids }) => { + let timer: ReturnType<typeof setTimeout> | undefined; + const off = client.onEvent(event => { + if (!ids.includes(event.root_id) || !/^(?:turn\.|agent\.(?:turn\.|admitted|prompt\.queued|subtree\.)|root\.|permission\.|question\.)/.test(event.kind) || timer) return; + timer = setTimeout(() => { + timer = undefined; + void runtime.queries.invalidateQueries({ queryKey: ['session-sidebar-summaries', runtimeId] }); + }, 250); + }); + return () => { off(); clearTimeout(timer); }; + }); + return () => releases.forEach(release => release()); + }, [runtime, targets]); + const activity = new Map<string, SessionNavigationSummary>(); + summaries.forEach((summary, index) => { + const target = targets[index]!; + if (target.enabled && !summary.error) for (const item of summary.data?.items ?? []) { + activity.set(sidebarRowKey('session', target.runtimeId, item.root_id), item); + } + }); + return activity; +} + +function DirectoryHost({ host, cwd, hosts, onConnect }: { host: HostConnection; cwd: string; hosts: readonly HostConnection[]; onConnect(): void }) { + const runtime = useRuntime(); + const connected = host.state === 'connected'; + const connecting = host.state === 'connecting' || host.state === 'reconnecting'; + const status = connected ? 'Connected' : connecting ? 'Reconnecting' : 'Offline'; + const name = hosts.some(other => other.id !== host.id && other.name === host.name) ? host.name + ' · ' + host.id : host.name; + const identity = name + ' · ' + status; + const target = host.profile?.target; + const connection = target?.kind === 'ssh' ? [target.user, target.host].filter(Boolean).join('@') + (target.port ? ':' + target.port : '') : host.endpoint; + return <Popover side="right" align="start" title={<span {...stylex.props(styles.hostHeading)}> + <span {...stylex.props(styles.hostHeadingRow)}> + <Globe size={14} aria-hidden="true" {...stylex.props(styles.detailIcon)} /> + <span {...stylex.props(layout.grow)}>{name}</span>{' '} + <span {...stylex.props(styles.hostStatus)}> + <Circle size={6} aria-hidden="true" fill={connected ? 'currentColor' : 'none'} {...stylex.props(styles.statusDot, connected && styles.connected)} /> + {status} + </span> + </span> + {connection && connection !== host.name && <span {...stylex.props(styles.hostConnection)}>{' '}{connection}</span>} + </span>} xstyle={styles.hostDetails} trigger={ + <button type="button" aria-label={identity + ' · ' + (cwd || 'Other sessions')} title={identity} {...stylex.props(styles.destination, styles.hostMetadata)}> + <span {...stylex.props(layout.ellipsis)}>{name}</span> + {!connected && <span {...stylex.props(styles.connectionLabel)}>{status}</span>} + <Circle size={6} aria-hidden="true" fill={connected ? 'currentColor' : 'none'} {...stylex.props(styles.statusDot, connected && styles.connected)} /> + </button> + }> + <span {...stylex.props(styles.hostPath)}> + <Folder size={14} aria-hidden="true" {...stylex.props(styles.detailIcon)} /> + <span>{cwd || 'Other sessions'}</span> + </span> + {host.error && <span role="status" {...stylex.props(styles.hostError)}>{host.error}</span>} + {!connected && <Button variant="ghost" xstyle={styles.hostAction} aria-label={'Reconnect ' + host.name} disabled={connecting} onClick={() => void runtime.connections.connect(host.id).catch(() => {})}> + <RotateCw size={14} aria-hidden="true" />Reconnect + </Button>} + <Button variant="ghost" xstyle={styles.hostAction} onClick={onConnect}><ArrowUpRight size={14} aria-hidden="true" />Manage servers</Button> + </Popover>; +} + +function HostFeedback({ host, catalog }: { host: HostConnection; catalog?: DeepReadonly<SessionListSnapshot> }) { const runtime = useRuntime(); - const needsSetup = host.localRuntime?.state === 'missing'; - const [collapsed, setCollapsed] = useState(false); - const expanded = !showHeading || !collapsed; - return <section aria-label={`${host.name} sessions`} {...stylex.props(styles.host, !expanded && styles.collapsedHost)}> - {showHeading && <button {...stylex.props(styles.destination, styles.hostHeading)} aria-expanded={!collapsed} title={host.endpoint} onClick={() => setCollapsed(value => !value)}> - {collapsed ? <ChevronRight size={13} /> : <ChevronDown size={13} />}<strong {...stylex.props(layout.grow, layout.ellipsis)}>{host.name}</strong> - <span {...stylex.props(layout.muted)}>{needsSetup ? '' : host.state === 'closed' ? 'Offline' : host.state === 'connected' ? '' : host.state}</span> - </button>} - {expanded && <> - {host.client && host.list ? <HostSidebar {...props} client={host.client} list={host.list} /> - : !needsSetup && <Button variant="ghost" disabled={host.state === 'connecting'} onClick={() => { - void runtime.connections.connect(host.id).catch(() => {}); - }}>{host.state === 'connecting' ? host.progress || 'Connecting…' : `Connect ${host.name}`}</Button>} - </>} - </section>; + if (host.localRuntime?.state === 'missing') return null; + if (!host.client || !host.list) return <Button variant="ghost" disabled={host.state === 'connecting'} onClick={() => { + void runtime.connections.connect(host.id).catch(() => {}); + }}>{host.state === 'connecting' ? host.progress || 'Connecting ' + host.name + '…' : 'Connect ' + host.name}</Button>; + const loading = catalog?.status === 'loading'; + const connected = host.state === 'connected'; + return <> + {!catalog?.page && !catalog?.error && <p role="status" {...stylex.props(styles.feedback)}>{connected ? 'Loading sessions · ' : 'Sessions unavailable · '}{host.name}</p>} + {catalog?.page?.has_more && <Button variant="ghost" disabled={loading || !connected} onClick={() => void host.list!.loadMore().catch(() => {})}>Load more sessions · {host.name}</Button>} + {connected && catalog?.error && <ErrorNotice type="resource" owner={'sessions:' + host.runtimeId} error={catalog.error.message} title={'Could not load sessions · ' + host.name} + action={<Button variant="ghost" disabled={loading} onClick={() => void host.list!.refresh().catch(() => {})}>Retry</Button>} />} + </>; } + function SidebarHeader({ onNavigate, headerAction, inset }: { onNavigate(): void; headerAction?: ReactNode; inset?: boolean; }) { const runtime = useRuntime(); const navigate = useNavigate(); @@ -105,66 +200,72 @@ function SidebarFooter({ onConnect }: { onConnect(): void }) { </button> </div>; } -function HostSidebar({ client, list, state, setState, onNavigate, scroll, content }: SidebarProps & SidebarScroll & { client: WhipClient; list: SessionListView }) { +function SessionRows({ hosts, state, setState, onNavigate, onConnect, scroll, content }: SidebarProps & SidebarScroll & { hosts: readonly HostConnection[] }) { const runtime = useRuntime(); - const catalog = useSessionListView(list); - const connection = useWhipConnection(client); + const actions = useSessionActions(); + const [actionError, setActionError] = useState<{ owner: string; error: unknown }>(); + const navigate = useNavigate(); + useSessionTabs(); + // Same snapshot adapter as Search: observe SDK catalogs, never mirror them in state. + const catalogs = useMemo(() => { + let snapshot = hosts.map(host => host.list?.getSnapshot()); + return { + getSnapshot: () => { + const next = hosts.map(host => host.list?.getSnapshot()); + if (next.some((value, index) => value !== snapshot[index])) snapshot = next; + return snapshot; + }, + subscribe: (listener: () => void) => { + const releases = hosts.map(host => host.list?.subscribe(listener)); + return () => releases.forEach(release => release?.()); + }, + }; + }, [hosts]); + const snapshots = useSyncExternalStore(catalogs.subscribe, catalogs.getSnapshot, catalogs.getSnapshot); const [collapseNotice, setCollapseNotice] = useState(''); - const runtimeId = client.getSnapshot().info?.runtime_id ?? ''; - const collapsed = state.hosts.find(host => host.runtimeId === runtimeId)?.collapsed ?? noCollapsedDirectories; - const collapse = (cwd: string, closed: boolean) => { + const collapse = (runtimeId: string, cwd: string, closed: boolean) => { const next = setDirectoryCollapsed(state, runtimeId, cwd, closed); setState(next); if (closed && state.hosts.some(host => host.collapsed.some(path => !next.hosts.find(item => item.runtimeId === host.runtimeId)?.collapsed.includes(path)))) { setCollapseNotice('Older directory collapse preferences were reset to keep sidebar storage within its limit.'); } }; - return <> - {collapseNotice && <p role="status">{collapseNotice}</p>} - <SessionRows client={client} scroll={scroll} content={content} page={catalog.page} loading={catalog.status === 'loading'} error={connection.state === 'connected' ? catalog.error?.message : undefined} - collapsed={collapsed} onCollapse={collapse} - onNavigate={onNavigate} retry={() => void list.refresh().catch(() => {})} loadMore={() => void list.loadMore().catch(() => {})} /> - </>; -} -function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry, scroll, content, collapsed = noCollapsedDirectories, onCollapse }: SidebarScroll & { - client: WhipClient; - page?: DeepReadonly<SessionCatalogPage>; - loading: boolean; - error?: string; - onNavigate(): void; - loadMore(): void; - retry(): void; - collapsed?: readonly string[]; - onCollapse?(cwd: string, closed: boolean): void; -}) { - const runtime = useRuntime(); - const actions = useSessionActions(); - const [actionError, setActionError] = useState<{ owner: string; error: unknown }>(); - const navigate = useNavigate(); - useSessionTabs(); - const connection = useWhipConnection(client); - const runtimeId = connection.info?.runtime_id ?? ''; const container = useRef<HTMLDivElement>(null); const [scrollMargin, setScrollMargin] = useState(0); - useLayoutEffect(() => { - const measure = () => setScrollMargin(container.current?.offsetTop ?? 0); + useEffect(() => { + const measure = () => { + const element = container.current, viewport = scroll.current; + if (element && viewport) setScrollMargin(element.getBoundingClientRect().top - viewport.getBoundingClientRect().top + viewport.scrollTop); + }; measure(); const observer = new ResizeObserver(measure); if (content.current) observer.observe(content.current); return () => observer.disconnect(); - }, [content]); + }, [content, scroll]); const [hoveredDirectory, setHoveredDirectory] = useState<string>(); const location = useLocation(); const selected = sessionDestination(location.pathname); - const items = page?.items; - const [directoryLimits, setDirectoryLimits] = useState<ReadonlyMap<string, number>>(() => new Map()); - const setDirectoryLimit = (cwd: string, limit: number) => setDirectoryLimits(previous => { - const next = new Map(previous); - next.delete(cwd); - if (limit > defaultDirectorySessionLimit) next.set(cwd, limit); - return new Map([...next].slice(-64)); + const [directoryLimits, setDirectoryLimits] = useState<ReadonlyMap<string, ReadonlyMap<string, number>>>(() => new Map()); + const setDirectoryLimit = (runtimeId: string, cwd: string, limit: number) => setDirectoryLimits(previous => { + const limits = new Map(previous.get(runtimeId)); + limits.delete(cwd); + if (limit > defaultDirectorySessionLimit) limits.set(cwd, limit); + const next = new Map([...previous].filter(([id]) => hosts.some(host => host.runtimeId === id && host.list))); + next.set(runtimeId, new Map([...limits].slice(-64))); + return next; }); - const rows = useMemo(() => sidebarRows(items ?? [], collapsed, directoryLimits), [items, collapsed, directoryLimits]); + useEffect(() => { + setDirectoryLimits(previous => { + const next = new Map([...previous].filter(([id]) => hosts.some(host => host.runtimeId === id && host.list))); + return next.size === previous.size ? previous : next; + }); + }, [hosts]); + const sources = useMemo(() => hosts.flatMap((host, index) => host.runtimeId && host.list ? [{ + runtimeId: host.runtimeId, items: snapshots[index]?.page?.items ?? [], + collapsed: state.hosts.find(item => item.runtimeId === host.runtimeId)?.collapsed ?? noCollapsedDirectories, + limits: directoryLimits.get(host.runtimeId), + }] : []), [hosts, snapshots, state.hosts, directoryLimits]); + const rows = useMemo(() => mixedSidebarRows(sources), [sources]); const [touch, setTouch] = useState(() => window.matchMedia('(pointer: coarse), (max-width: 767px)').matches); useEffect(() => { const media = window.matchMedia('(pointer: coarse), (max-width: 767px)'); @@ -174,65 +275,32 @@ function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry const rowHeight = (index: number) => rows[index]?.kind === 'directory' ? (touch ? 48 : 36) : touch ? 44 : 28; const offsets = useMemo(() => { let offset = 0; - return new Map(rows.map((row, index) => { const start = offset; offset += rowHeight(index); return [row.key, start]; })); + return new Map(rows.map((row, index) => { const start = offset; offset += rowHeight(index) + sidebarRowGap; return [row.key, start]; })); }, [rows, touch]); - const virtual = useVirtualizer({ count: rows.length, getScrollElement: () => scroll.current, scrollMargin, estimateSize: rowHeight, overscan: 5, getItemKey: index => rows[index]!.key }); + const virtual = useVirtualizer({ count: rows.length, getScrollElement: () => scroll.current, scrollMargin, estimateSize: rowHeight, gap: sidebarRowGap, overscan: 5, getItemKey: index => rows[index]!.key }); const visibleRows = virtual.getVirtualItems(); - const ids = useMemo(() => visibleRows.flatMap(item => { - const row = rows[item.index]; - return row?.kind === 'session' ? [row.session.id] : []; - }).sort(), [visibleRows, rows]); - const [visible, setVisible] = useState(() => document.visibilityState !== 'hidden'); - useEffect(() => { const change = () => setVisible(document.visibilityState !== 'hidden'); document.addEventListener('visibilitychange', change); return () => document.removeEventListener('visibilitychange', change); }, []); - const supported = connection.info?.negotiated_capabilities?.includes('session_summaries') ?? false; - const summaries = useQuery({ - queryKey: ['session-sidebar-summaries', runtimeId, ids], - queryFn: async ({ signal }) => { - const items = []; - for (let offset = 0; offset < ids.length; offset += 32) { - const page = await client.sessions.summaries(ids.slice(offset, offset + 32), { signal }); - items.push(...page.items); - } - return { items }; - }, - enabled: visible && connection.state === 'connected' && supported && ids.length > 0, - refetchInterval: visible && connection.state === 'connected' ? 2000 : false, - refetchIntervalInBackground: false, - refetchOnWindowFocus: true, - staleTime: 0, - gcTime: 0, - }); - const activity = new Map(summaries.data?.items.map(item => [item.root_id, item])); - const activityStale = !supported || connection.state !== 'connected' || !!summaries.error; - useEffect(() => { - if (!visible || connection.state !== 'connected' || !supported || !ids.length) return; - let timer: ReturnType<typeof setTimeout> | undefined; - const off = client.onEvent(event => { - if (!ids.includes(event.root_id) || !/^(?:turn\.|agent\.(?:turn\.|admitted|prompt\.queued|subtree\.)|root\.|permission\.|question\.)/.test(event.kind) || timer) return; - timer = setTimeout(() => { - timer = undefined; - void runtime.queries.invalidateQueries({ queryKey: ['session-sidebar-summaries', runtimeId] }); - }, 250); - }); - return () => { off(); clearTimeout(timer); }; - }, [client, connection.state, ids, runtime, runtimeId, supported, visible]); + const activity = useSidebarActivity(hosts, visibleRows.map(item => rows[item.index]!)); // Virtual rows can move beneath a stationary pointer during scroll or refresh. useLayoutEffect(() => { - setHoveredDirectory(container.current?.querySelector<HTMLElement>('[data-sidebar-cwd]:hover')?.dataset.sidebarCwd); + setHoveredDirectory(container.current?.querySelector<HTMLElement>('[data-sidebar-group]:hover')?.dataset.sidebarGroup); }, [visibleRows, rows]); const anchor = useRef<{ key: string; group?: string; offset: number } | null>(null); const rememberAnchor = () => { const top = scroll.current?.scrollTop ?? 0; const visible = virtual.getVirtualItems().find(row => row.end > top); const row = visible && rows[visible.index]; - anchor.current = row && visible && visible.start <= top ? { key: row.key, group: row.kind === 'session' ? `directory:${row.session.cwd}` : undefined, offset: top - visible.start } : null; + anchor.current = row && visible && visible.start <= top ? { key: row.key, group: row.directoryKey, offset: top - visible.start } : null; }; + const onScroll = useRef(rememberAnchor); + useLayoutEffect(() => { onScroll.current = rememberAnchor; }); useEffect(() => { const element = scroll.current; - const update = () => { rememberAnchor(); setHoveredDirectory(container.current?.querySelector<HTMLElement>('[data-sidebar-cwd]:hover')?.dataset.sidebarCwd); }; + // Keep this listener attached: the virtualizer can synchronously render during + // the same scroll event, before later native listeners have been invoked. + const update = () => { onScroll.current(); setHoveredDirectory(container.current?.querySelector<HTMLElement>('[data-sidebar-group]:hover')?.dataset.sidebarGroup); }; element?.addEventListener('scroll', update); return () => element?.removeEventListener('scroll', update); - }); + }, [scroll]); useLayoutEffect(() => { virtual.measure(); const saved = anchor.current; @@ -240,44 +308,48 @@ function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry if (start !== undefined && start !== null) virtual.scrollToOffset(scrollMargin + start + saved!.offset); }, [offsets, scrollMargin, virtual]); // Only route changes request a reveal. Polling must not undo a user's collapse. - const pendingReveal = useRef<string | undefined>(undefined); - useLayoutEffect(() => { pendingReveal.current = selected?.runtimeId === runtimeId ? selected.rootId : undefined; }, [location.pathname, runtimeId]); + const pendingReveal = useRef<ReturnType<typeof sessionDestination>>(undefined); + useLayoutEffect(() => { pendingReveal.current = sessionDestination(location.pathname); }, [location.pathname]); useLayoutEffect(() => { - const id = pendingReveal.current; - if (!id) return; - const session = items?.find(item => item.id === id); - if (!session) return; - if (collapsed.includes(session.cwd)) { onCollapse?.(session.cwd, false); return; } - const index = rows.findIndex(row => row.kind === 'session' && row.session.id === id); + const target = pendingReveal.current; + if (!target) return; + const source = sources.find(source => source.runtimeId === target.runtimeId); + const session = source?.items.find(item => item.id === target.rootId); + if (!source || !session) return; + if (source.collapsed.includes(session.cwd)) { collapse(target.runtimeId, session.cwd, false); return; } + const index = rows.findIndex(row => row.kind === 'session' && row.runtimeId === target.runtimeId && row.session.id === target.rootId); if (index < 0) { - const position = items!.filter(item => item.cwd === session.cwd).findIndex(item => item.id === id); - setDirectoryLimit(session.cwd, Math.ceil((position + 1) / defaultDirectorySessionLimit) * defaultDirectorySessionLimit); + const position = source.items.filter(item => item.cwd === session.cwd).findIndex(item => item.id === target.rootId); + setDirectoryLimit(target.runtimeId, session.cwd, Math.ceil((position + 1) / defaultDirectorySessionLimit) * defaultDirectorySessionLimit); return; } virtual.scrollToIndex(index, { align: 'auto' }); pendingReveal.current = undefined; - rememberAnchor(); - }); + }, [location.pathname, sources, rows, virtual]); return <div ref={container} - onPointerOver={event => { if (event.pointerType !== 'touch') setHoveredDirectory((event.target as Element).closest<HTMLElement>('[data-sidebar-cwd]')?.dataset.sidebarCwd); }} + onPointerOver={event => { if (event.pointerType !== 'touch') setHoveredDirectory((event.target as Element).closest<HTMLElement>('[data-sidebar-group]')?.dataset.sidebarGroup); }} onPointerLeave={() => setHoveredDirectory(undefined)}> <div style={{ height: virtual.getTotalSize(), position: 'relative' }}> {visibleRows.map(row => { const item = rows[row.index]!; - if (item.kind === 'more') return <button key={item.key} type="button" data-sidebar-cwd={item.cwd} + const runtimeId = item.runtimeId; + const host = hosts.find(host => host.runtimeId === runtimeId)!; + const collapsed = state.hosts.find(host => host.runtimeId === runtimeId)?.collapsed ?? noCollapsedDirectories; + if (item.kind === 'more') return <button key={item.key} type="button" data-sidebar-cwd={item.cwd} data-sidebar-runtime={runtimeId} data-sidebar-group={item.directoryKey} aria-label={`${item.expanded ? 'Less' : 'More'} sessions in ${item.cwd || 'Other sessions'}`} aria-expanded={item.visibleCount > defaultDirectorySessionLimit} - onClick={() => setDirectoryLimit(item.cwd, item.expanded ? defaultDirectorySessionLimit : item.visibleCount + defaultDirectorySessionLimit)} + onClick={() => setDirectoryLimit(runtimeId, item.cwd, item.expanded ? defaultDirectorySessionLimit : item.visibleCount + defaultDirectorySessionLimit)} style={{ position: 'absolute', width: '100%', top: 0, height: row.size, transform: `translateY(${row.start - scrollMargin}px)` }} {...stylex.props(styles.destination, styles.moreButton)}> {item.expanded ? <ChevronRight size={12} aria-hidden="true" /> : <ChevronDown size={12} aria-hidden="true" />} {item.expanded ? 'Less' : 'More'} </button>; - if (item.kind === 'directory') return <div key={item.key} data-sidebar-directory={item.cwd} data-sidebar-cwd={item.cwd} + if (item.kind === 'directory') return <div key={item.key} data-sidebar-directory={item.cwd} data-sidebar-cwd={item.cwd} data-sidebar-runtime={runtimeId} data-sidebar-group={item.directoryKey} style={{ position: 'absolute', width: '100%', top: 0, height: row.size, transform: `translateY(${row.start - scrollMargin}px)` }} {...stylex.props(styles.group, directoryMarker)}> - <button title={item.cwd || 'Other sessions'} aria-label={item.cwd || 'Other sessions'} aria-expanded={!collapsed.includes(item.cwd)} - onClick={() => onCollapse?.(item.cwd, !collapsed.includes(item.cwd))} {...stylex.props(styles.destination, styles.groupButton, layout.grow)}> - <span {...stylex.props(layout.ellipsis)}>{item.label}</span><span data-directory-caret {...stylex.props(styles.caret, hoveredDirectory === item.cwd && styles.revealed)}>{collapsed.includes(item.cwd) ? <ChevronRight size={12} /> : <ChevronDown size={12} />}</span> - </button> + <Tooltip label={host.name + ' · ' + (item.cwd || 'Other sessions')}><button title={item.cwd || 'Other sessions'} aria-label={item.cwd || 'Other sessions'} aria-description={host.name} aria-expanded={!collapsed.includes(item.cwd)} + onClick={() => collapse(runtimeId, item.cwd, !collapsed.includes(item.cwd))} {...stylex.props(styles.destination, styles.groupButton, layout.grow)}> + <span {...stylex.props(layout.ellipsis)}>{item.label}</span><span data-directory-caret {...stylex.props(styles.caret, hoveredDirectory === item.directoryKey && styles.revealed)}>{collapsed.includes(item.cwd) ? <ChevronRight size={12} /> : <ChevronDown size={12} />}</span> + </button></Tooltip> + {(!host.local || host.state !== 'connected') && <DirectoryHost host={host} cwd={item.cwd} hosts={hosts} onConnect={onConnect} />} {item.cwd && <Link to="/" search={{ new: 1, cwd: item.cwd, runtimeId }} preload={false} onClick={event => { if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; event.preventDefault(); @@ -289,7 +361,7 @@ function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry const saved = runtime.tabs.preferred(runtimeId, session.id); const active = selected?.runtimeId === runtimeId && selected.rootId === session.id; const menuItems = actions.items({ runtimeId, rootId: session.id, title: session.title, archived: session.archived }); - return <div key={item.key} data-sidebar-session={session.id} data-sidebar-cwd={session.cwd} + return <div key={item.key} data-sidebar-session={session.id} data-sidebar-cwd={session.cwd} data-sidebar-runtime={runtimeId} data-sidebar-group={item.directoryKey} style={{ position: 'absolute', width: '100%', top: 0, height: row.size, transform: `translateY(${row.start - scrollMargin}px)` }}> <ContextMenu items={menuItems} onOpenChange={actions.prepare}><div {...stylex.props(styles.sessionRow, sessionMarker, active && styles.selected)}> <WorkspaceExternalSource id={`sidebar:${JSON.stringify([runtimeId, session.id])}`} @@ -303,8 +375,8 @@ function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry catch (error) { event.preventDefault(); setActionError({ owner: `${runtimeId}:${session.id}`, error }); } }} {...stylex.props(styles.sessionLink)}> <span {...stylex.props(styles.indicator)}>{session.pinned ? <Pin size={12} aria-label="Pinned" /> - : sessionNeedsInput(activity.get(session.id), activityStale) ? <MessageSquareWarning size={12} {...stylex.props(styles.attention)} aria-label="Needs your input" /> - : sessionBusy(activity.get(session.id), activityStale) ? <Spinner size={10} label="Session is busy" /> + : sessionNeedsInput(activity.get(item.key)) ? <MessageSquareWarning size={12} {...stylex.props(styles.attention)} aria-label="Needs your input" /> + : sessionBusy(activity.get(item.key)) ? <Spinner size={10} label="Session is busy" /> : <Circle size={5} aria-hidden="true" />}</span> <span {...stylex.props(layout.grow)}><span {...stylex.props(styles.title, layout.ellipsis)}>{session.title || 'Untitled session'}</span> </span> @@ -318,9 +390,9 @@ function SessionRows({ client, page, loading, error, onNavigate, loadMore, retry </div>; })} </div> - {!items?.length && <p {...stylex.props(layout.muted)}>{loading ? 'Loading sessions…' : 'No saved sessions yet.'}</p>} - {page?.has_more && <Button variant="ghost" disabled={loading} onClick={loadMore}>Load more sessions</Button>} - {error && <ErrorNotice type="resource" owner={`sessions:${runtimeId}`} error={error} title="Could not load sessions" action={<Button variant="ghost" disabled={loading} onClick={retry}>Retry</Button>} />} + {collapseNotice && <p role="status" {...stylex.props(styles.feedback)}>{collapseNotice}</p>} + {!rows.length && hosts.length > 0 && hosts.every((host, index) => host.state === 'connected' && snapshots[index]?.status === 'live') && <p {...stylex.props(styles.feedback)}>No saved sessions yet.</p>} + {hosts.map((host, index) => <HostFeedback key={host.id} host={host} catalog={snapshots[index]} />)} {actionError && <ErrorNotice type="action" owner={actionError.owner} error={actionError.error} title="Could not open session" onDismiss={() => setActionError(undefined)} />} </div>; } diff --git a/packages/app/src/settings/agents.tsx b/packages/app/src/settings/agents.tsx index 8dd5803f9..6bb9ca8bb 100644 --- a/packages/app/src/settings/agents.tsx +++ b/packages/app/src/settings/agents.tsx @@ -3,15 +3,14 @@ import { useQuery } from '@tanstack/react-query'; import { useForm, useStore } from '@tanstack/react-form'; import type { WhipClient } from '@whip/sdk'; import { defineAgent, type Definition } from '@whip/sdk/agents'; -import { Button, Checkbox, Input, Switch, Textarea } from '@whip/ui'; +import { Button, Checkbox, Collapsible, Dialog, Field, Fieldset, Input, Switch, Textarea } from '@whip/ui'; import * as stylex from '@stylexjs/stylex'; import { surface, typography, scale } from '@whip/ui/tokens.stylex'; import { useRuntime } from '../context'; import { ErrorNotice } from '../error-feedback'; -import { layout } from '../styles'; import { definitionIdPattern } from '../session-tabs'; import { definitionsQueryKey, useDefinitions, type DefinitionSummary } from '../definitions'; -import { SettingsGroup, SettingRow, settingsSection } from './section-layout'; +import { SettingsGroup } from './section-layout'; import { useSettingsEdits } from './unsaved'; /** The editable, data-only part of a definition. Tools and hooks need code and stay with the SDK. */ @@ -59,6 +58,7 @@ export function AgentsSettings({ client, enabled }: { client: WhipClient; enable enabled: definitions.supported, }); const [editing, setEditing] = useState<{ key: string; values: AgentValues }>({ key: 'new', values: blank }); + const [editorOpen, setEditorOpen] = useState(false); const [loadError, setLoadError] = useState<unknown>(); if (!definitions.supported) { return enabled ? <SettingsGroup title="Agents"><p role="status" {...stylex.props(styles.note)}>This host does not support agent definitions. Update it to author agents here.</p></SettingsGroup> : null; @@ -69,10 +69,11 @@ export function AgentsSettings({ client, enabled }: { client: WhipClient; enable try { const record = await client.agents.get(item.id, item.built_in ? undefined : item.revision); setEditing({ key: `${item.id}:${item.revision}`, values: agentValues(record.definition, record.built_in) }); + setEditorOpen(true); } catch (error) { setLoadError(error); } } return <> - <SettingsGroup title="Agents on this host" action={<Button variant="ghost" disabled={!enabled} onClick={() => setEditing({ key: `new:${Date.now()}`, values: blank })}>New agent</Button>}> + <SettingsGroup title="Agents on this host" action={<Button id="agents" variant="ghost" disabled={!enabled} onClick={() => { setEditing({ key: `new:${Date.now()}`, values: blank }); setEditorOpen(true); }}>New agent</Button>}> {definitions.query.isPending && <p role="status" {...stylex.props(styles.note)}>Loading agents…</p>} {definitions.query.error && <ErrorNotice type="resource" owner={`${runtimeId}:definitions`} title="Could not load agents" error={definitions.query.error} />} <ul {...stylex.props(styles.list)} aria-label="Agent definitions"> @@ -86,16 +87,17 @@ export function AgentsSettings({ client, enabled }: { client: WhipClient; enable </ul> <ErrorNotice type="action" owner={`${runtimeId}:definition-open`} title="Could not open the agent" error={loadError} /> </SettingsGroup> - <AgentEditor key={editing.key} client={client} enabled={enabled} initial={editing.values} + <AgentEditor key={editing.key} client={client} enabled={enabled} initial={editing.values} open={editorOpen} onOpenChange={setEditorOpen} modules={catalog.data?.definition.modules ?? []} capabilities={catalog.data?.definition.capabilities ?? []} /> </>; } -function AgentEditor({ client, enabled, initial, modules, capabilities }: { client: WhipClient; enabled: boolean; initial: AgentValues; modules: readonly string[]; capabilities: readonly string[] }) { +function AgentEditor({ client, enabled, initial, open, onOpenChange, modules, capabilities }: { client: WhipClient; enabled: boolean; initial: AgentValues; open: boolean; onOpenChange: (open: boolean) => void; modules: readonly string[]; capabilities: readonly string[] }) { const runtime = useRuntime(); const [error, setError] = useState(''); const [errorType, setErrorType] = useState<'validation' | 'action'>('action'); const [notice, setNotice] = useState(''); + const nameInput = useRef<HTMLInputElement>(null); const request = useRef<AbortController | null>(null); const saved = useRef(false); useEffect(() => () => { request.current?.abort(); request.current = null; }, [client]); @@ -104,7 +106,7 @@ function AgentEditor({ client, enabled, initial, modules, capabilities }: { clie onSubmit: async ({ value }) => { if (!enabled || request.current) return; setError(''); setNotice(''); setErrorType('action'); - if (!definitionIdPattern.test(value.id.trim())) { setErrorType('validation'); setError('Use a lowercase id of letters, digits, and hyphens, 2 to 64 characters, starting with a letter.'); return; } + if (!definitionIdPattern.test(value.id.trim())) { setErrorType('validation'); setError('Use a lowercase name of letters, digits, and hyphens, 2 to 64 characters, starting with a letter.'); return; } if (!value.modules.length) { setErrorType('validation'); setError('Select at least one host module.'); return; } const controller = new AbortController(); request.current = controller; @@ -129,54 +131,50 @@ function AgentEditor({ client, enabled, initial, modules, capabilities }: { clie }); const toggle = (list: string[], name: string, checked: boolean) => checked ? [...list.filter(item => item !== name), name] : list.filter(item => item !== name); const text = (name: 'id' | 'projectFiles', label: string, description: string, placeholder?: string) => <form.Field key={name} name={name}>{field => - <SettingRow id={name === 'id' ? 'agents' : `agent_${name}`} label={label} description={description}> - <Input aria-label={label} xstyle={settingsSection.control} disabled={!enabled || submitting} placeholder={placeholder} value={field.state.value} + <Field label={label} description={description}> + <Input ref={name === 'id' ? nameInput : undefined} xstyle={name === 'projectFiles' ? styles.identifier : undefined} disabled={!enabled || submitting} placeholder={placeholder} value={field.state.value} onBlur={field.handleBlur} onChange={event => field.handleChange(event.target.value)} /> - </SettingRow>} + </Field>} </form.Field>; - const prose = (name: 'persona' | 'rules', label: string, description: string, placeholder: string) => <form.Field key={name} name={name}>{field => - <SettingRow id={`agent_${name}`} label={label} description={description}> - <Textarea aria-label={label} xstyle={styles.prose} rows={name === 'rules' ? 5 : 2} disabled={!enabled || submitting} placeholder={placeholder} + const prose = (name: 'persona' | 'rules', label: string, placeholder: string) => <form.Field key={name} name={name}>{field => + <Field label={label}> + <Textarea xstyle={styles.prose} rows={name === 'rules' ? 3 : 2} disabled={!enabled || submitting} placeholder={placeholder} value={field.state.value} onBlur={field.handleBlur} onChange={event => field.handleChange(event.target.value)} /> - </SettingRow>} + </Field>} </form.Field>; const flag = (name: 'skillDiscovery' | 'standingInstructions' | 'autoTitle' | 'goalLoop', label: string, description: string) => <form.Field key={name} name={name}>{field => - <SettingRow id={`agent_${name}`} label={label} description={description}> - <Switch aria-label={label} checked={field.state.value} disabled={!enabled || submitting} onCheckedChange={field.handleChange} /> - </SettingRow>} + <Switch aria-labelledby={`agent-${name}-label`} label={<span id={`agent-${name}-label`}>{label}</span>} description={description} checked={field.state.value} disabled={!enabled || submitting} onCheckedChange={field.handleChange} />} </form.Field>; const choices = (name: 'modules' | 'capabilities', label: string, description: string, options: readonly string[]) => <form.Field key={name} name={name}>{field => - <SettingRow id={`agent_${name}`} label={label} description={description}> - <div role="group" aria-label={label} {...stylex.props(styles.choices)}> + <Fieldset legend={label} description={description} xstyle={styles.choiceField}> + <div {...stylex.props(styles.choices)}> {options.map(option => <Checkbox key={option} label={option} checked={field.state.value.includes(option)} disabled={!enabled || submitting} onCheckedChange={checked => field.handleChange(toggle(field.state.value, option, checked === true))} />)} {!options.length && <span {...stylex.props(styles.note)}>Loading the host's catalog…</span>} </div> - </SettingRow>} + </Fieldset>} </form.Field>; - return <form {...stylex.props(layout.column)} aria-label="Agent editor" onSubmit={event => { event.preventDefault(); void form.handleSubmit(); }}> - <SettingsGroup title={initial.id ? `Edit ${initial.id}` : 'New agent'}> - {text('id', 'Agent id', 'Lowercase letters, digits, and hyphens. Registering an existing id adds a revision; running sessions keep theirs.', 'support-triage')} - {prose('persona', 'Persona', 'The first sentence of the system prompt: who the agent is.', 'You triage support tickets for a small engineering team.')} - {prose('rules', 'Rules', 'Operating rules that follow the runtime guide. One per line.', 'Operating rules:\n- Look tickets up before describing them.')} - {text('projectFiles', 'Project files', 'Instruction files read along the project directory chain, comma separated. Empty disables discovery.', 'CLAUDE.md, AGENTS.md')} - {flag('skillDiscovery', 'Skill discovery', 'Offer the project and user skill catalogs.')} - {flag('standingInstructions', 'Standing instructions', 'Append the user’s me.md rules.')} - </SettingsGroup> - <SettingsGroup title="Reach"> - {choices('modules', 'Host modules', 'What the model is told about and may call. The kernel installs only these.', modules)} - {choices('capabilities', 'Capabilities', 'Authority the agent receives at session start. Children can only narrow it.', capabilities)} - </SettingsGroup> - <SettingsGroup title="Surface"> - {flag('autoTitle', 'Automatic title', 'Name the session from its first message.')} - {flag('goalLoop', 'Goal loop', 'Allow goal commands that continue the agent until it reports done.')} - </SettingsGroup> - <div {...stylex.props(layout.row)}> - <Button type="submit" variant="primary" loading={submitting} disabled={!enabled || submitting || !dirty && !!notice}>Register agent</Button> - {notice && <span role="status" {...stylex.props(styles.note)}>{notice}</span>} - </div> - {error && <ErrorNotice type={errorType} owner="agent-editor" title="Could not register the agent" error={error} />} - </form>; + return <Dialog open={open} onOpenChange={onOpenChange} initialFocus={nameInput} title={initial.id ? `Edit ${initial.id}` : 'New agent'} xstyle={styles.editor} + footer={<Button type="submit" form="agent-editor" variant="primary" loading={submitting} disabled={!enabled || submitting || !dirty && !!notice}>Register agent</Button>}> + <form id="agent-editor" aria-label="Agent editor" {...stylex.props(styles.form)} onSubmit={event => { event.preventDefault(); void form.handleSubmit(); }}> + {text('id', 'Agent Name', 'Lowercase letters, digits, and hyphens. Reuse a name to add a revision.', 'support-triage')} + {prose('persona', 'Persona', 'Who is this agent, and what does it do?')} + {prose('rules', 'Rules', 'Operating instructions, one per line.')} + {choices('modules', 'Host modules', 'Functions the agent can call. Select at least one.', modules)} + {choices('capabilities', 'Capabilities', 'Authority granted at session start. Children can only narrow it.', capabilities)} + <Collapsible title="More options"> + <div {...stylex.props(styles.options)}> + {text('projectFiles', 'Project files', 'Comma-separated instruction files. Leave empty to skip discovery.', 'CLAUDE.md, AGENTS.md')} + {flag('skillDiscovery', 'Skill discovery', 'Offer project and user skill catalogs.')} + {flag('standingInstructions', 'Standing instructions', 'Include your me.md rules.')} + {flag('autoTitle', 'Automatic title', 'Name sessions from their first message.')} + {flag('goalLoop', 'Goal loop', 'Continue until the agent reports done.')} + </div> + </Collapsible> + {error && <ErrorNotice type={errorType} owner="agent-editor" title="Could not register the agent" error={error} />} + {notice && <p role="status" {...stylex.props(styles.note)}>{notice}</p>} + </form> + </Dialog>; } const styles = stylex.create({ @@ -185,6 +183,11 @@ const styles = stylex.create({ identity: { display: 'flex', flexDirection: 'column', gap: 2, minWidth: 0 }, name: { fontWeight: 500 }, note: { fontSize: typography.size12, color: surface.secondaryText, margin: 0, lineHeight: 1.5 }, - prose: { width: '100%', minHeight: 60, resize: 'vertical', fontSize: typography.size13 }, - choices: { display: 'flex', flexWrap: 'wrap', gap: scale.space2, maxWidth: 420 }, + editor: { width: 'min(800px, calc(100vw - 32px))', padding: scale.space5, gap: scale.space4 }, + form: { display: 'flex', flexDirection: 'column', gap: scale.space4, minWidth: 0 }, + identifier: { fontFamily: typography.mono }, + prose: { minHeight: 60 }, + choiceField: { gap: scale.space2 }, + choices: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 9em), 1fr))', columnGap: scale.space2, rowGap: scale.space1 }, + options: { display: 'flex', flexDirection: 'column', gap: scale.space3, paddingTop: scale.space3 }, }); diff --git a/packages/app/src/settings/configuration.tsx b/packages/app/src/settings/configuration.tsx index e35995ed8..480a416c0 100644 --- a/packages/app/src/settings/configuration.tsx +++ b/packages/app/src/settings/configuration.tsx @@ -12,11 +12,12 @@ import { PermissionModeControl } from '../permission-mode'; import { layout } from '../styles'; import { SettingsGroup, SettingRow, settingsSection } from './section-layout'; import { useSettingsEdits } from './unsaved'; +import { CompactionSettings, compactionError, compactionPatch, type CompactionValues } from '../compaction-settings'; type Category = 'providers' | 'execution'; const providerFields = ['default_model', 'default_provider', 'default_effort', 'default_permission_mode'] as const; const executionFields = ['default_execution_engine', 'compact_model', 'compact_provider', 'compact_percent', 'goal_max_rounds', 'max_retries', 'import_claude', 'import_codex'] as const; -type Values = Pick<RuntimeConfiguration, typeof providerFields[number] | typeof executionFields[number]>; +type Values = Omit<Pick<RuntimeConfiguration, typeof providerFields[number] | typeof executionFields[number]>, 'compact_percent'> & CompactionValues; function values(config: RuntimeConfiguration): Values { return { default_model: config.default_model, default_provider: config.default_provider, default_effort: config.default_effort, @@ -28,14 +29,14 @@ function values(config: RuntimeConfiguration): Values { } /** Each editor may write only its owned fields, even when another category has changed. */ -export function configurationPatch(category: Category, value: Values, revision: string): ConfigurationUpdate { +export function configurationPatch(category: Category, value: Values, base: RuntimeConfiguration): ConfigurationUpdate { if (category === 'providers') return { - revision, default_model: value.default_model, default_provider: value.default_provider, default_effort: value.default_effort, + revision: base.revision, default_model: value.default_model, default_provider: value.default_provider, default_effort: value.default_effort, ...(value.default_permission_mode === undefined ? {} : { default_permission_mode: value.default_permission_mode }), }; return { default_execution_engine: value.default_execution_engine, - revision, compact_model: value.compact_model, compact_provider: value.compact_provider, compact_percent: value.compact_percent, + revision: base.revision, ...compactionPatch(value, base), goal_max_rounds: value.goal_max_rounds, max_retries: value.max_retries, import_claude: value.import_claude, import_codex: value.import_codex, }; } @@ -81,13 +82,14 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider request.current = controller; const queryKey = ['runtime-configuration', client.getSnapshot().info?.runtime_id]; try { - if (category === 'execution' && (!Number.isInteger(value.compact_percent) || value.compact_percent < 0 || value.compact_percent > 100 - || !Number.isInteger(value.goal_max_rounds) || value.goal_max_rounds < 0 || !Number.isInteger(value.max_retries) || value.max_retries < 0)) { + if (category === 'execution' && (!Number.isInteger(value.goal_max_rounds) || value.goal_max_rounds < 0 || !Number.isInteger(value.max_retries) || value.max_retries < 0)) { setErrorType('validation'); - setError('Use whole numbers: compaction from 0 to 100%, and non-negative goal rounds and retries.'); + setError('Use non-negative whole numbers for goal rounds and retries.'); return; } - const result = await client.configuration.update(configurationPatch(category, value, base.revision), { signal: controller.signal }); + const compactError = category === 'execution' ? compactionError(value, base) : undefined; + if (compactError) { setErrorType('validation'); setError(compactError); return; } + const result = await client.configuration.update(configurationPatch(category, value, base), { signal: controller.signal }); if (controller.signal.aborted) return; runtime.queries.setQueryData(queryKey, result); setBase(result); form.reset(values(result)); saved.current = true; @@ -106,6 +108,7 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider const provider = useStore(form.store, state => state.values.default_provider) || defaultProvider || ''; const models = catalogModels(catalog.data?.result, provider); const efforts = modelEfforts(models, model); + const currentValues = useStore(form.store, state => state.values); const dirty = useStore(form.store, state => !state.isDefaultValue); const submitting = useStore(form.store, state => state.isSubmitting); useSettingsEdits({ @@ -114,19 +117,14 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider discard: () => { setBase(config); form.reset(values(config)); setError(''); }, save: async () => { saved.current = false; await form.handleSubmit(); return saved.current; }, }); - const textField = (name: 'compact_model' | 'compact_provider', label: string, description: string) => <form.Field key={name} name={name}>{field => + const numberField = (name: 'goal_max_rounds' | 'max_retries', label: string, description: string) => <form.Field key={name} name={name}>{field => <SettingRow id={name} label={label} description={description}> - <Input aria-label={label} xstyle={settingsSection.control} disabled={!enabled || submitting} value={field.state.value} - onBlur={field.handleBlur} onChange={event => field.handleChange(event.target.value)} /> - </SettingRow>} - </form.Field>; - const numberField = (name: 'compact_percent' | 'goal_max_rounds' | 'max_retries', label: string, description: string, max?: number) => <form.Field key={name} name={name}>{field => - <SettingRow id={name} label={label} description={description}> - <Input aria-label={label} xstyle={settingsSection.control} type="number" min={0} max={max} step={1} disabled={!enabled || submitting} + <Input aria-label={label} xstyle={settingsSection.control} type="number" min={0} step={1} disabled={!enabled || submitting} value={Number.isNaN(field.state.value) ? '' : field.state.value} onBlur={field.handleBlur} onChange={event => field.handleChange(event.target.valueAsNumber)} /> </SettingRow>} </form.Field>; - return <form {...stylex.props(layout.column)} onSubmit={event => { event.preventDefault(); void form.handleSubmit(); }}> + // Validate only edited compaction values; native min/max would block untouched legacy defaults. + return <form noValidate {...stylex.props(layout.column)} onSubmit={event => { event.preventDefault(); void form.handleSubmit(); }}> {category === 'providers' ? <SettingsGroup title="Defaults for new work"> <SettingRow id="default_model" label="Default model" description="Choose the model and provider for new work."> <CatalogModelPicker label="Default model" settings model={model} provider={provider} catalog={catalog.data?.result} @@ -160,9 +158,12 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider </SettingRow>}</form.Field> </SettingsGroup> <SettingsGroup title="Context compaction"> - {textField('compact_model', 'Compaction model', 'Model used to summarize conversation context.')} - {textField('compact_provider', 'Compaction provider', 'Provider used for context compaction.')} - {numberField('compact_percent', 'Compaction threshold', 'Percentage of the context window at which compaction begins.', 100)} + <CompactionSettings client={client} value={currentValues} base={base} disabled={!enabled || submitting} + onChange={next => { + form.setFieldValue('compact_model', next.compact_model); + form.setFieldValue('compact_provider', next.compact_provider); + form.setFieldValue('compact_percent', next.compact_percent); + }} /> </SettingsGroup> <SettingsGroup title="Execution limits"> {numberField('goal_max_rounds', 'Goal round limit', 'Maximum rounds for goal-driven work.')} diff --git a/packages/app/src/settings/navigation.ts b/packages/app/src/settings/navigation.ts index 59176437e..58d59fade 100644 --- a/packages/app/src/settings/navigation.ts +++ b/packages/app/src/settings/navigation.ts @@ -38,9 +38,8 @@ export const settingEntries: readonly SettingEntry[] = [ { id: 'default_model', section: 'providers', label: 'Default model', keywords: 'default provider model route' }, { id: 'default_effort', section: 'providers', label: 'Default reasoning effort', keywords: 'thinking low medium high' }, { id: 'default_permission_mode', section: 'providers', label: 'Default permission level', keywords: 'permissions approval ask full access automatic prompt' }, - { id: 'compact_model', section: 'execution', label: 'Compaction model', keywords: 'context summary' }, - { id: 'compact_provider', section: 'execution', label: 'Compaction provider', keywords: 'context summary' }, - { id: 'compact_percent', section: 'execution', label: 'Compaction threshold', keywords: 'context percentage' }, + { id: 'compact_model', section: 'execution', label: 'Summary model', keywords: 'context compaction summary provider automatic custom' }, + { id: 'compact_percent', section: 'execution', label: 'When to compact', keywords: 'context compaction threshold percentage automatic' }, { id: 'goal_max_rounds', section: 'execution', label: 'Goal rounds', keywords: 'agent limit execution' }, { id: 'max_retries', section: 'execution', label: 'Maximum retries', keywords: 'agent errors execution' }, { id: 'import_claude', section: 'execution', label: 'Import Claude configuration', keywords: 'integration' }, diff --git a/packages/app/src/sidebar-state.ts b/packages/app/src/sidebar-state.ts index 60e9cd399..6adf1d05d 100644 --- a/packages/app/src/sidebar-state.ts +++ b/packages/app/src/sidebar-state.ts @@ -86,6 +86,39 @@ export function sidebarRows(items: readonly Session[], collapsed: readonly strin return rows; } +export type HostSidebarRow = SidebarRow & { runtimeId: string; cwd: string; directoryKey: string }; +export const sidebarRowKey = (kind: SidebarRow['kind'], runtimeId: string, id: string) => JSON.stringify([kind, runtimeId, id]); + +/** Mix directories, not sessions: each daemon still owns its catalog's pin/recency order. */ +export function mixedSidebarRows(hosts: readonly { + runtimeId: string; + items: readonly Session[]; + collapsed?: readonly string[]; + limits?: ReadonlyMap<string, number>; +}[]): HostSidebarRow[] { + const groups: { key: string; updated: number; rows: HostSidebarRow[] }[] = []; + for (const host of hosts) { + const latest = new Map<string, number>(); + for (const session of host.items) { + const updated = Date.parse(session.updated_at); + if (Number.isFinite(updated)) latest.set(session.cwd, Math.max(latest.get(session.cwd) ?? -Infinity, updated)); + } + let group: typeof groups[number] | undefined; + for (const row of sidebarRows(host.items, host.collapsed, host.limits)) { + const cwd = row.kind === 'session' ? row.session.cwd : row.cwd; + const directoryKey = sidebarRowKey('directory', host.runtimeId, cwd); + if (row.kind === 'directory') { + group = { key: directoryKey, updated: latest.get(cwd) ?? -Infinity, rows: [] }; + groups.push(group); + } + group!.rows.push({ ...row, cwd, runtimeId: host.runtimeId, directoryKey, + key: sidebarRowKey(row.kind, host.runtimeId, row.kind === 'session' ? row.session.id : cwd) }); + } + } + return groups.sort((a, b) => (a.updated === b.updated ? 0 : a.updated > b.updated ? -1 : 1) + || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0)).flatMap(group => group.rows); +} + export function newSessionSearch(search: Record<string, unknown>): { new?: 1; cwd?: string; runtimeId?: string } { const runtimeId = typeof search.runtimeId === 'string' && search.runtimeId.length > 0 && search.runtimeId.length <= 256 && !/[\u0000-\u001f]/.test(search.runtimeId) ? search.runtimeId : undefined; const cwd = runtimeId && typeof search.cwd === 'string' && search.cwd.length > 0 && search.cwd.length <= 4096 && !/[\u0000-\u001f]/.test(search.cwd) ? search.cwd : undefined; diff --git a/packages/app/src/timeline.tsx b/packages/app/src/timeline.tsx index 253c84062..82df514bc 100644 --- a/packages/app/src/timeline.tsx +++ b/packages/app/src/timeline.tsx @@ -45,7 +45,7 @@ import { ActivityHeader, ActivityStep, ActivityDetail, InlineAgent, type Transcr import { MotionContext, RowMotion, transcriptMotion, useTranscriptMotion, type Arrival } from './transcript-motion'; import { MarkdownBlock, isMarkdownRow, markdownRows, useCoalescedTranscript } from './streaming-markdown'; import { DiagramChoices, MarkdownCodeBlock, MarkdownReadiness } from './markdown-code-block'; -import { isActivityGroup, isAgentActivity, activityItems, responseCopies, type ActivityItem, type ActivityGroup, type ConversationActivityRow } from './chat-activity-rows'; +import { isActivityGroup, isAgentActivity, activityItems, responseCopies, type ActivityItem, type ActivityGroup, type ConversationActivityRow, type ResponseActions } from './chat-activity-rows'; import { conversationRows, messagePresentation, type ImagePart, type TimelineRow } from './conversation-rows'; import { DesignInputAttachments } from './design-input-attachments'; import { BrowserDesignAttachment } from './browser-design-attachment'; @@ -182,15 +182,11 @@ const styles = stylex.create({ imageDialog: { width: 'min(960px, 90vw)' }, imagePreview: { display: 'block', width: '100%', height: 'auto', maxHeight: '75vh', objectFit: 'contain' }, actions: { - position: 'absolute', - bottom: 0, - right: 0, display: 'flex', alignItems: 'center', - justifyContent: 'flex-end', gap: 8, minHeight: { default: 28, '@media (pointer: coarse)': 44 }, - pointerEvents: { default: 'none', [stylex.when.ancestor(':hover', messageMarker)]: 'auto', [stylex.when.ancestor(':focus-within', messageMarker)]: 'auto', '@media (pointer: coarse)': 'auto' }, + pointerEvents: { default: 'none', [stylex.when.ancestor(':hover', messageMarker)]: 'auto', [stylex.when.ancestor(':focus-within', messageMarker)]: 'auto', [stylex.when.ancestor(':has([aria-expanded="true"])', messageMarker)]: 'auto', '@media (pointer: coarse)': 'auto' }, fontSize: typography.size12, color: surface.secondaryText, opacity: { @@ -201,7 +197,8 @@ const styles = stylex.create({ '@media (pointer: coarse)': 1, }, }, - responseActions: { display: 'flex', alignItems: 'center', paddingBlock: '2px 12px', color: surface.secondaryText }, + userActions: { position: 'absolute', bottom: 0, right: 0, justifyContent: 'flex-end' }, + responseActions: { justifyContent: 'flex-start', paddingBlock: '2px 12px' }, actionButton: { width: { default: 28, '@media (pointer: coarse)': 44 }, minHeight: { default: 28, '@media (pointer: coarse)': 44 }, padding: 0 }, delivery: { fontSize: typography.size12, color: surface.secondaryText, marginTop: 4 }, byline: { @@ -503,8 +500,6 @@ export const MessageRow = memo(function MessageRow({ const disclosure = ['tool', 'reasoning', 'mailbox', 'internal'].includes(row.role); const user = row.role === 'user'; const assistant = row.role === 'assistant'; - const stamp = row.sentAt ? new Date(row.sentAt) : undefined; - const time = stamp && Number.isFinite(stamp.getTime()) ? stamp : undefined; const copy = <MessageCopy key={row.id} owner={row.id} label="Copy message" text={row.text} />; return ( <article @@ -539,15 +534,8 @@ export const MessageRow = memo(function MessageRow({ {row.delivery} </div> )} - <div data-message-actions {...stylex.props(styles.actions)}> - {time && ( - <time dateTime={row.sentAt} title={time.toLocaleString()}> - {time.toLocaleTimeString(undefined, { - hour: 'numeric', - minute: '2-digit', - })} - </time> - )} + <div data-message-actions {...stylex.props(styles.actions, styles.userActions)}> + <MessageTime sentAt={row.sentAt} /> {copy} {row.seq !== undefined && historyAction && ( <Menu @@ -599,6 +587,33 @@ export const MessageRow = memo(function MessageRow({ ); }); +function MessageTime({ sentAt }: { sentAt?: string }) { + const time = sentAt ? new Date(sentAt) : undefined; + if (!time || !Number.isFinite(time.getTime())) return null; + return <time dateTime={sentAt} title={time.toLocaleString()} aria-label={time.toLocaleString()}> + {time.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })} + </time>; +} + +function ResponseFooter({ owner, response, historyAction, rewindDisabled }: { + owner: string; response: ResponseActions; + historyAction?(endpoint: number, action: 'fork' | 'rewind'): void; + rewindDisabled: boolean; +}) { + const endpoint = response.endpoint; + const canAct = endpoint !== undefined && !!historyAction; + if (!response.text && !response.sentAt && !canAct) return null; + return <div data-response-actions {...stylex.props(styles.actions, styles.responseActions)}> + {canAct && <Menu trigger={<IconButton variant="ghost" xstyle={styles.actionButton} label="Response history actions"><MoreHorizontal size={14} /></IconButton>} + items={[ + { id: 'fork', label: 'Fork from here', onSelect: () => historyAction(endpoint, 'fork') }, + { id: 'rewind', label: 'Rewind to here…', disabled: rewindDisabled, onSelect: () => historyAction(endpoint, 'rewind') }, + ]} />} + {!!response.text && <MessageCopy owner={owner} label={response.label} text={response.text} />} + <MessageTime sentAt={response.sentAt} /> + </div>; +} + function MessageCopy({ owner, label, text }: { owner: string; label: string; text: string }) { const runtime = useRuntime(); const [error, setError] = useState<unknown>(); @@ -612,6 +627,9 @@ function MessageCopy({ owner, label, text }: { owner: string; label: string; tex export function Timeline({ readingActionsRef, rows: incomingRows, + responseHistoryAction, + historyThroughSeq, + rewindDisabled = false, agents = [], activeTurnId, onAgent, @@ -637,6 +655,9 @@ export function Timeline({ }: { readingActionsRef?: Ref<ReadingListActions>; rows: ConversationActivityRow[]; + responseHistoryAction?(endpoint: number, action: 'fork' | 'rewind'): void; + historyThroughSeq?: number; + rewindDisabled?: boolean; agents?: readonly TranscriptAgent[]; activeTurnId?: string; onAgent?(id: string): void; @@ -695,7 +716,7 @@ export function Timeline({ const copies = useMemo(() => responseCopies(rows.map(row => { const prose = storedProse.get(row.id); return prose && prose.digest === row.body?.digest ? { ...row, body: undefined, copyText: prose.text } : row; - }), active || !connected || !historyReady, hasMore), [rows, storedProse, active, connected, historyReady, hasMore]); + }), active || !historyReady, hasMore, latestMissing ? undefined : historyThroughSeq), [rows, storedProse, active, historyReady, hasMore, latestMissing, historyThroughSeq]); const parsed = useRef<Parameters<typeof markdownRows>[1]>(new Map()); const blocks = useMemo(() => markdownRows(rows, parsed.current), [rows]); const region = useRef<HTMLDivElement>(null); @@ -788,7 +809,7 @@ export function Timeline({ return next; }); }; - type DisplayRow = { id: string; seq?: number; memberIds?: readonly string[]; memberSeqs?: readonly number[]; source: typeof blocks[number]; group?: ActivityGroup; item?: ActivityItem; detail?: boolean; open?: boolean; last?: boolean; copy?: { text: string; label: string } }; + type DisplayRow = { id: string; seq?: number; memberIds?: readonly string[]; memberSeqs?: readonly number[]; source: typeof blocks[number]; group?: ActivityGroup; item?: ActivityItem; detail?: boolean; open?: boolean; last?: boolean; copy?: ResponseActions }; const displayRows: DisplayRow[] = []; for (const [blockIndex, row] of blocks.entries()) { if (isActivityGroup(row)) { @@ -801,7 +822,7 @@ export function Timeline({ displayRows.push({ id: item.id, seq: item.row?.seq ?? item.cell?.seq, source: row, group: row, item, open: detail, last: index === items.length - 1 && !detail }); if (detail) displayRows.push({ id: `${item.id}:detail`, seq: item.row?.seq ?? item.cell?.seq, source: row, group: row, item, detail: true }); }); - } else displayRows.push({ id: row.id, seq: row.seq, memberIds: row.memberIds, source: row }); + } else displayRows.push({ id: row.id, seq: row.seq, memberIds: row.memberIds, memberSeqs: row.memberSeqs, source: row }); const owner = isMarkdownRow(row) ? row.ownerId : row.id; const following = blocks[blockIndex + 1]; if (!isMarkdownRow(row) || !following || !isMarkdownRow(following) || following.ownerId !== owner) displayRows.at(-1)!.copy = copies.get(owner); @@ -813,7 +834,7 @@ export function Timeline({ label="Conversation" earlierLabel="Load earlier messages" footer={footer} renderRow={row => { const source = row.source; - return <> + return <div data-response-end={row.copy ? true : undefined} {...stylex.props(messageMarker)}> <RowMotion arrival={row.group || isAgentActivity(source) ? arrivals.current.get(row.id) : undefined} closing={!!row.item && closing.has(row.group!.id)}> {source.historyGap ? <HistoryGapControl gap={source.historyGap} connected={connected} load={() => loadGap?.(source.historyGap!.toSeq) ?? Promise.resolve()} /> : row.group ? row.item ? row.detail @@ -832,8 +853,10 @@ export function Timeline({ ? <StoredMessageRow row={source} scope={messageScope} connected={connected} historyRevision={historyRevision} onProse={retainProse} readBody={readBody} detailsOnly /> : undefined} />} </RowMotion> - {row.copy && <div data-response-actions {...stylex.props(styles.responseActions)}><MessageCopy key={source.id} owner={source.id} label={row.copy.label} text={row.copy.text} /></div>} - </>; + {row.copy && <ResponseFooter key={source.id} owner={source.id} response={row.copy} + historyAction={connected && historyReady ? responseHistoryAction : undefined} + rewindDisabled={rewindDisabled || active || row.copy.endpoint === historyThroughSeq} />} + </div>; }} /> </div></MotionContext.Provider></DiagramChoices.Provider>; } diff --git a/packages/app/src/trace-view.tsx b/packages/app/src/trace-view.tsx index 86665c3ad..4d292f4b2 100644 --- a/packages/app/src/trace-view.tsx +++ b/packages/app/src/trace-view.tsx @@ -263,6 +263,11 @@ function SpanDetails({ width, view, node, domainStartMs, now, agents }: { width: <dl {...stylex.props(styles.stats)}> {stats.map(([label, value]) => <div key={label} {...stylex.props(styles.stat)}><dt {...stylex.props(styles.statLabel)}>{label}</dt><dd {...stylex.props(styles.statValue)}>{value}</dd></div>)} </dl> + {span.kind === 'llm' && text(attrs.purpose) === 'compaction' && <div {...stylex.props(styles.section)}> + <span {...stylex.props(styles.sectionLabel)}>Summary route</span> + <p {...stylex.props(styles.notice)}>{text(attrs.model) || span.name} · {text(attrs.provider) || 'Provider not recorded'}</p> + {text(attrs.compaction_fallback) && <p {...stylex.props(styles.notice)}>{text(attrs.compaction_fallback)}</p>} + </div>} {bodies.map(([label, value]) => <div key={label} {...stylex.props(styles.section)}> <CodeBlock code={value} label={label} xstyle={styles.code} /> </div>)} diff --git a/packages/app/test/chat-activity.test.tsx b/packages/app/test/chat-activity.test.tsx index 8809fe2aa..1ab6c9bd9 100644 --- a/packages/app/test/chat-activity.test.tsx +++ b/packages/app/test/chat-activity.test.tsx @@ -345,3 +345,93 @@ it('missing raw records split activity, prevent cross-gap call binding, and mark history.gaps[0]!.fromSeq = 4; expect(timelineRows(history, [], true).find(row => row.historyGap)?.id).toBe('history-gap:1:4'); }); + +it('keeps the full raw response endpoint through rich parts, folded results, and activity groups', () => { + const first = '2026-09-27T19:00:00Z'; + const last = '2026-09-27T19:02:00Z'; + const history = { revision: '1', throughSeq: 7, nextSeq: 0, hasMore: false, loading: false, truncated: false, messages: [ + { seq: 1, message: { role: 'user', authored: true, content: 'Start' } }, + { seq: 2, message: { role: 'assistant', sent_at: first, content: 'Before.', tool_calls: [{ id: 'a', type: 'function', function: { name: 'rlm_exec', arguments: '{}' } }], + presentation: { version: 1, parts: [{ id: 'text-a', kind: 'text', start: 0, end: 7 }, { id: 'tool-a', kind: 'tool', call_id: 'a', tool_name: 'rlm_exec' }] } } }, + { seq: 3, message: { role: 'tool', tool_call_id: 'a', content: 'Not copied' } }, + { seq: 4, message: { role: 'user', content: 'Internal image delivery' } }, + { seq: 5, message: { role: 'assistant', sent_at: last, content: 'After.', tool_calls: [{ id: 'b', type: 'function', function: { name: 'rlm_exec', arguments: '{}' } }], + presentation: { version: 1, parts: [{ id: 'text-b', kind: 'text', start: 0, end: 6 }, { id: 'tool-b', kind: 'tool', call_id: 'b', tool_name: 'rlm_exec' }] } } }, + { seq: 6, message: { role: 'tool', tool_call_id: 'b', content: 'Trailing result' } }, + { seq: 7, message: { role: 'user', authored: true, content: 'Next' } }, + ] } as Parameters<typeof timelineRows>[0]; + const raw = timelineRows(history, [], true); + expect(raw.find(row => row.callId === 'b')).toMatchObject({ seq: 5, memberSeqs: [6] }); + const grouped = conversationActivityRows(raw, [cell('a', 2), cell('b', 5)]); + const end = grouped.at(-2)!; + expect(end).toMatchObject({ memberSeqs: [5, 6] }); + expect([...responseCopies(grouped, false, false, 7)]).toEqual([[end.id, { text: 'Before.\n\nAfter.', label: 'Copy response', sentAt: last, endpoint: 6 }]]); + expect(responseCopies(grouped.slice(0, -1), false, false, 6).get(end.id)?.endpoint).toBe(6); +}); + +it('carries rich text/image/stored-body timestamps and the last assistant tool-only time without inventing dates', () => { + const stamp = '2026-09-27T20:00:00Z'; + const history = { revision: '1', throughSeq: 2, nextSeq: 0, hasMore: false, loading: false, truncated: false, messages: [ + { seq: 1, message: { role: 'assistant', sent_at: stamp, content: [{ type: 'text', text: 'Hello' }, { type: 'image_url', image_url: { url: 'data:image/png;base64,AAAA' } }], presentation: { version: 1, parts: [{ id: 'text', kind: 'text', start: 0, end: 5 }] } } }, + { seq: 2, role: 'assistant', sent_at: stamp, body: { reference_id: 'stored', size: '999', digest: 'a', media_type: 'application/json' }, presentation: { version: 1, parts: [{ id: 'partial', kind: 'text', text: 'Partial' }] } }, + ] } as Parameters<typeof timelineRows>[0]; + const rows = timelineRows(history, [], true); + expect(rows.filter(row => row.role === 'assistant').every(row => row.sentAt === stamp)).toBe(true); + const later = { ...tool('later', 3), assistantSeq: 3, sentAt: '2026-09-27T20:01:00Z' }; + const projected = conversationActivityRows([...rows, later], [cell('later', 3)]); + expect([...responseCopies(projected, false, false, 3).values()][0]).toMatchObject({ sentAt: later.sentAt, label: 'Copy visible response', endpoint: 3 }); + for (const sentAt of [undefined, 'invalid']) { + const response = responseCopies([{ id: 'one', role: 'assistant', text: 'Answer', seq: 1, sentAt: stamp }, { ...later, sentAt }], false, false, 3).get(later.id); + expect(response?.sentAt).toBeUndefined(); + } +}); + +it('offers no uncertain history endpoint across gaps, partial prefixes, live members, or an unloaded suffix', () => { + const answer: TimelineRow = { id: 'answer', role: 'assistant', text: '**Answer**', seq: 2 }; + for (const rows of [ + [answer, { ...tool('tail', 4) }], + [answer, { ...tool('tail', 3), historyUncertain: true }], + [answer, { ...tool('tail', 3), live: true }], + [answer, { id: 'unknown', role: 'notice', text: 'Interrupted' }], + ]) expect([...responseCopies(rows, false, false, 4).values()][0]?.endpoint).toBeUndefined(); + expect(responseCopies([answer], false, true, 2).get(answer.id)).toMatchObject({ label: 'Copy visible response' }); + expect(responseCopies([answer], false, true, 2).get(answer.id)?.endpoint).toBeUndefined(); + expect(responseCopies([answer], false).get(answer.id)?.endpoint).toBeUndefined(); + expect(responseCopies([answer], true, false, 2).size).toBe(0); + const gap: TimelineRow = { id: 'gap', role: 'history-gap', text: '', historyGap: { fromSeq: 3, toSeq: 4, status: 'paused' } }; + expect(responseCopies([answer, gap], false, false, 4).get(answer.id)?.endpoint).toBeUndefined(); + const groupWithLive = conversationActivityRows([answer, { ...tool('x', 3), memberSeqs: [4] }, tool('y')], [cell('x', 3), cell('y')]); + expect([...responseCopies(groupWithLive, false, false, 4).values()][0]?.endpoint).toBeUndefined(); +}); + +it('supports image-only controls but no tool-only footer and bounds Markdown copy including separators', () => { + const image: TimelineRow = { id: 'image', role: 'assistant', seq: 1, text: '', images: [{ url: 'data:image/png;base64,AAAA' }], sentAt: '2026-09-27T20:00:00Z' }; + expect(responseCopies([image], false, false, 1).get(image.id)).toMatchObject({ text: '', endpoint: 1, sentAt: image.sentAt }); + expect(responseCopies([{ ...tool('only', 1), assistantSeq: 1, sentAt: image.sentAt }], false, false, 1).size).toBe(0); + const large: TimelineRow = { id: 'large', role: 'assistant', text: 'x'.repeat(256 * 1024 - 1), seq: 1 }; + const response = responseCopies([large, { id: 'tail', role: 'assistant', text: 'y', seq: 2 }], false, false, 2).get('tail')!; + expect(response.text.length).toBe(256 * 1024 - 1); + expect(response.label).toBe('Copy visible response'); + expect(response.endpoint).toBe(2); +}); + +it.each([false, true])('keeps the last assistant timestamp when interrupted prose is recorded on a tool result (stored=%s)', stored => { + const stamp = '2026-09-27T20:00:00Z'; + const presentation = { version: 1, turn_id: 'turn', parts: [ + { id: 'result', kind: 'result', call_id: 'call' }, + { id: 'pending', kind: 'text', text: 'Interrupted partial answer' }, + ] }; + const history = { revision: '1', throughSeq: 3, nextSeq: 0, hasMore: false, loading: false, truncated: false, messages: [ + { seq: 1, message: { role: 'user', authored: true, content: 'Start' } }, + { seq: 2, message: { role: 'assistant', sent_at: stamp, content: 'Working.', tool_calls: [{ id: 'call', type: 'function', function: { name: 'rlm_exec', arguments: '{}' } }] } }, + stored + ? { seq: 3, role: 'tool', presentation, body: { reference_id: 'result', size: '999', digest: 'a', media_type: 'application/json' } } + : { seq: 3, message: { role: 'tool', tool_call_id: 'call', content: 'Tool result', presentation } }, + ] } as Parameters<typeof timelineRows>[0]; + const raw = timelineRows(history, [], true); + expect(raw.find(row => row.partId === 'pending')).toMatchObject({ role: 'assistant', sourceRole: 'tool', seq: 3 }); + const rows = conversationActivityRows(raw, [cell('call', 2)]); + expect([...responseCopies(rows, false, false, 3).values()]).toEqual([ + { text: 'Working.\n\nInterrupted partial answer', label: 'Copy visible response', sentAt: stamp, endpoint: 3 }, + ]); +}); diff --git a/packages/app/test/conversation-history-errors.test.tsx b/packages/app/test/conversation-history-errors.test.tsx index 2db7fcf57..f8e337658 100644 --- a/packages/app/test/conversation-history-errors.test.tsx +++ b/packages/app/test/conversation-history-errors.test.tsx @@ -10,6 +10,7 @@ import { SessionContent } from '../src/conversation'; vi.mock('@tanstack/react-router', async importOriginal => ({ ...await importOriginal<typeof import('@tanstack/react-router')>(), useNavigate: () => vi.fn(async () => {}), + Link: ({ children }: { children: ReactNode }) => <a>{children}</a>, })); // Keep the real action menu and dialogs; inspector and transcript rendering are // unrelated to the ownership of a pending history operation. @@ -19,8 +20,9 @@ vi.mock('@whip/ui', async importOriginal => ({ })); vi.mock('../src/timeline', async importOriginal => ({ ...await importOriginal<typeof import('../src/timeline')>(), - Timeline: ({ historyAction }: ComponentProps<typeof import('../src/timeline').Timeline>) => <> + Timeline: ({ historyAction, responseHistoryAction }: ComponentProps<typeof import('../src/timeline').Timeline>) => <> {(['rewind', 'fork'] as const).map(action => <button key={action} onClick={() => historyAction?.({ id: 'h:1', seq: 1, role: 'user', text: 'Hello' }, action)}>{action} message</button>)} + {(['rewind', 'fork'] as const).map(action => <button key={action + 'response'} disabled={!responseHistoryAction} onClick={() => responseHistoryAction?.(6, action)}>{action} response</button>)} </>, })); vi.mock('../src/composer', () => ({ Composer: () => null })); @@ -35,26 +37,27 @@ vi.mock('../src/session-actions', () => ({ useSessionActions: () => ({ items: () const runtimes: AppRuntime[] = []; afterEach(() => { for (const runtime of runtimes.splice(0)) runtime.dispose(); }); -function fixture() { +function fixture(agentId = 'root') { const values = new Map<string, string>(); const storage = { keys: () => [...values.keys()], getItem: (key: string) => values.get(key) ?? null, setItem: (key: string, value: string) => { values.set(key, value); }, removeItem: (key: string) => { values.delete(key); } }; const runtime = new AppRuntime({ defaultEndpoint: 'http://127.0.0.1:8080', storage, copy: async () => {}, openExternal: async () => {}, download: async () => {} }); runtimes.push(runtime); vi.spyOn(runtime.connections, 'isAttached').mockReturnValue(true); const connection = { state: 'connected', info: { runtime_id: 'host' } }; - const snapshot = { + let snapshot = { status: 'live', collections: {}, - root: { root_id: 'root', meta: {}, history_revision: '1', active_turns: {}, presentation: [], inbox: [] }, - history: { root: { revision: '1', throughSeq: 1, nextSeq: 1, hasMore: false, loading: false, truncated: false, messages: [{ seq: 1, message: { role: 'user', content: 'Hello' } }] } }, + root: { root_id: 'root', meta: {}, history_revision: '1', active_turns: {} as Record<string, string>, presentation: [], agent_presentations: {}, inbox: [] }, + history: { [agentId]: { revision: '1', throughSeq: 8, nextSeq: 1, hasMore: false, loading: false, truncated: false, messages: [{ seq: 1, message: { role: 'user', content: 'Hello' } }] } }, }; const view = { - subscribe: () => () => {}, getSnapshot: () => snapshot, + subscribe: () => () => {}, getSnapshot: () => snapshot, openAgent: vi.fn(async () => {}), closeAgent: vi.fn(), session: { rootId: 'root', client: { subscribe: () => () => {}, getSnapshot: () => connection, supports: () => false }, history: { clear: vi.fn(), rewind: vi.fn() }, fork: vi.fn() }, } as unknown as SessionView; const run = vi.spyOn(runtime, 'run'); - render(<RuntimeContext.Provider value={runtime}><UIProvider><SessionContent kind="chat" view={view} expectedRuntimeId="host" agentId="root" panel="agents" /></UIProvider></RuntimeContext.Provider>); - return { run }; + const app = () => <RuntimeContext.Provider value={runtime}><UIProvider><SessionContent kind="chat" view={view} expectedRuntimeId="host" agentId={agentId} panel="agents" /></UIProvider></RuntimeContext.Provider>; + const mounted = render(app()); + return { run, view, runtime, connection, snapshot, update: () => { snapshot = { ...snapshot }; mounted.rerender(app()); } }; } it.each(['rewind', 'fork'] as const)('does not leak a closed clear-history failure into a new %s dialog', async action => { @@ -78,3 +81,92 @@ it.each(['rewind', 'fork'] as const)('does not leak a closed clear-history failu await waitFor(() => expect(within(dialog).getByRole('alert')).toBeTruthy()); expect(dialog.querySelector('[data-error-type="action"]')?.textContent).toContain('Current history changed'); }); + +it.each(['fork', 'rewind'] as const)('keeps the selected response with the correct %s command cut', async action => { + const f = fixture(); + f.run.mockResolvedValue({ status: 'completed' } as never); + fireEvent.click(screen.getByRole('button', { name: action + ' response' })); + const dialog = screen.getByRole('dialog', { name: action === 'fork' ? 'Fork from here?' : 'Rewind to here?' }); + expect(dialog.textContent).toContain(action === 'rewind' ? 'Keep this response' : 'including this response'); + fireEvent.click(within(dialog).getByRole('button', { name: 'Confirm ' + action })); + await waitFor(() => expect(f.run).toHaveBeenCalledTimes(1)); + if (action === 'fork') expect(f.view.session.fork).toHaveBeenCalledWith({ cut: 6, expected_revision: '1' }); + else expect(f.view.session.history.rewind).toHaveBeenCalledWith(7, '1'); +}); + +it.each(['fork', 'rewind'] as const)('does not change the existing user %s cut', async action => { + const f = fixture(); + f.run.mockResolvedValue({ status: 'completed' } as never); + fireEvent.click(screen.getByRole('button', { name: action + ' message' })); + fireEvent.click(screen.getByRole('button', { name: 'Confirm ' + action })); + await waitFor(() => expect(f.run).toHaveBeenCalledTimes(1)); + if (action === 'fork') expect(f.view.session.fork).toHaveBeenCalledWith({ cut: 1, expected_revision: '1' }); + else expect(f.view.session.history.rewind).toHaveBeenCalledWith(1, '1'); +}); + +it.each(['fork', 'rewind'] as const)('rejects stale response %s confirmation locally without replacing the selected revision', async action => { + const f = fixture(); + fireEvent.click(screen.getByRole('button', { name: action + ' response' })); + f.snapshot.root.history_revision = '2'; + f.snapshot.history.root.revision = '2'; + f.update(); + fireEvent.click(screen.getByRole('button', { name: 'Confirm ' + action })); + expect(screen.getByRole('dialog').textContent).toContain('History has changed'); + expect(f.run).not.toHaveBeenCalled(); +}); + +it('blocks response rewind when the root starts working or there is no later history', () => { + const f = fixture(); + f.snapshot.root.active_turns.root = 'running'; f.update(); + fireEvent.click(screen.getByRole('button', { name: 'rewind response' })); + expect(screen.queryByRole('dialog')).toBeNull(); + delete f.snapshot.root.active_turns.root; f.snapshot.history.root.throughSeq = 6; f.update(); + fireEvent.click(screen.getByRole('button', { name: 'rewind response' })); + expect(screen.queryByRole('dialog')).toBeNull(); + f.snapshot.history.root.throughSeq = 8; f.update(); + fireEvent.click(screen.getByRole('button', { name: 'rewind response' })); + f.snapshot.root.active_turns.root = 'running'; f.update(); + expect((screen.getByRole('button', { name: 'Confirm rewind' }) as HTMLButtonElement).disabled).toBe(true); + expect(f.run).not.toHaveBeenCalled(); +}); + +it('disables response actions in child transcripts', () => { + const child = fixture('child'); + expect((screen.getByRole('button', { name: 'fork response' }) as HTMLButtonElement).disabled).toBe(true); + expect(child.run).not.toHaveBeenCalled(); +}); + +it.each(['disconnected', 'wrong-runtime'] as const)('cannot submit a response action after %s', mode => { + const f = fixture(); + fireEvent.click(screen.getByRole('button', { name: 'fork response' })); + if (mode === 'disconnected') f.connection.state = 'disconnected'; + else f.connection.info.runtime_id = 'another-host'; + f.update(); + if (mode === 'wrong-runtime') expect(screen.queryByRole('button', { name: 'Confirm fork' })).toBeNull(); + else { + expect((screen.getByRole('button', { name: 'Confirm fork' }) as HTMLButtonElement).disabled).toBe(true); + fireEvent.click(screen.getByRole('button', { name: 'Confirm fork' })); + } + expect(f.run).not.toHaveBeenCalled(); +}); + +it('guards fork tab limits', async () => { + const f = fixture(); + for (let i = 0; i < 32; i++) f.runtime.tabs.open('host', 'root-' + i); + fireEvent.click(screen.getByRole('button', { name: 'fork response' })); + fireEvent.click(screen.getByRole('button', { name: 'Confirm fork' })); + expect(screen.getByRole('dialog').textContent).toContain('32 open session tabs'); + expect(f.run).not.toHaveBeenCalled(); +}); + +it('does not submit a response history command twice while confirmation is pending', async () => { + const f = fixture(); + let resolve!: (outcome: never) => void; + f.run.mockReturnValueOnce(new Promise(done => { resolve = done; })); + fireEvent.click(screen.getByRole('button', { name: 'rewind response' })); + const confirm = screen.getByRole('button', { name: 'Confirm rewind' }); + fireEvent.click(confirm); fireEvent.click(confirm); + expect(f.view.session.history.rewind).toHaveBeenCalledTimes(1); + expect((confirm as HTMLButtonElement).disabled).toBe(true); + await act(async () => resolve({ status: 'completed' } as never)); +}); diff --git a/packages/app/test/inspector.test.tsx b/packages/app/test/inspector.test.tsx index 8c26d9c29..ee3d8d1f9 100644 --- a/packages/app/test/inspector.test.tsx +++ b/packages/app/test/inspector.test.tsx @@ -1,3 +1,4 @@ +import userEvent from '@testing-library/user-event'; import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; @@ -94,11 +95,13 @@ function fixture() { submit: vi.fn((operation: string, payload: unknown) => ({ operation, payload })), invoke: vi.fn(async () => ({ result: {} })), call: vi.fn(async () => ({})), + providers: { catalogs: vi.fn(async () => ({ result: { models: {}, providers: { provider: { available: true }, offline: { available: false } }, catalogs: { provider: { models: [{ id: 'original' }, { id: 'my-model' }] }, offline: { models: [{ id: 'offline-model' }] } } } })) }, configuration: { get: vi.fn(async () => ({ revision: '1', compact_model: 'original', compact_provider: 'provider', + compact_percent: 0, })), update: vi.fn(async () => ({})), }, @@ -122,6 +125,11 @@ function fixture() { platform: { download: vi.fn() }, } as unknown as AppRuntime; const props: InspectorProps = { view, root, connected: true, agentId: 'root' }; + const wrapper = (node: ReactNode) => <RuntimeContext.Provider value={runtime}> + <ThemeProvider initialTheme="light"><UIProvider><QueryClientProvider client={queries}> + {node} + </QueryClientProvider></UIProvider></ThemeProvider> + </RuntimeContext.Provider>; return { client, root, @@ -133,17 +141,8 @@ function fixture() { state = { ...state, ...next }; listeners.forEach((listener) => listener()); }, - render(node: ReactNode) { - return render( - <RuntimeContext.Provider value={runtime}> - <ThemeProvider initialTheme="light"> - <UIProvider> - <QueryClientProvider client={queries}>{node}</QueryClientProvider> - </UIProvider> - </ThemeProvider> - </RuntimeContext.Provider>, - ); - }, + wrapper, + render(node: ReactNode) { return render(wrapper(node)); }, }; } const agent = (id: string, controls: string[]) => ({ @@ -234,12 +233,10 @@ describe('session inspector controls', () => { new Error('configuration revision changed'), ); f.render(<Compaction {...f.props} />); - await waitFor(() => - expect((screen.getByLabelText('Compaction model') as HTMLInputElement).value).toBe( - 'original', - ), - ); - fireEvent.change(screen.getByLabelText('Compaction model'), { target: { value: 'my-model' } }); + await screen.findByText('Custom · original · provider'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + fireEvent.click(await screen.findByRole('option', { name: 'my-model · provider' })); act(() => f.queries.setQueryData(['inspector-compaction-config', 'runtime'], { revision: '2', @@ -638,3 +635,110 @@ it('explains unavailable live MCP refresh without sending an unsupported action' expect(screen.getByText(/This host does not support live MCP refresh/)).toBeTruthy(); expect(f.client.submit).not.toHaveBeenCalled(); }); + +describe('compaction defaults', () => { + it('shows Automatic, chooses a connected pair, and explicitly reloads after saving', async () => { + const f = fixture(); + f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: '', compact_provider: '', compact_percent: 0 }); + f.render(<Compaction {...f.props} />); + expect(await screen.findByText('Automatic · conversation model and provider')).toBeDefined(); + expect(screen.getByText('Automatic · 50%')).toBeDefined(); + expect(screen.queryByRole('combobox', { name: 'Summary model mode' })).toBeNull(); + expect(f.client.providers.catalogs).not.toHaveBeenCalled(); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.click(screen.getByRole('combobox', { name: 'Summary model mode' })); + await userEvent.click(await screen.findByRole('option', { name: 'Custom', exact: true })); + fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + const option = await screen.findByRole('option', { name: 'my-model · provider' }); + expect(screen.queryByRole('option', { name: 'offline-model · offline' })).toBeNull(); + fireEvent.click(option); + expect(f.client.configuration.update).not.toHaveBeenCalled(); + expect(f.run).not.toHaveBeenCalled(); + fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); + await waitFor(() => expect(f.run).toHaveBeenCalled()); + expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_model: 'my-model', compact_provider: 'provider' }); + expect(f.client.submit).toHaveBeenCalledWith('session.reload', {}, { rootId: 'root' }); + expect(f.client.configuration.update.mock.invocationCallOrder[0]).toBeLessThan(f.client.submit.mock.invocationCallOrder[0]!); + }); + + it('clears both override fields on Automatic without changing the threshold', async () => { + const f = fixture(); f.render(<Compaction {...f.props} />); + await screen.findByText('Custom · original · provider'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.click(screen.getByRole('combobox', { name: 'Summary model mode' })); + await userEvent.click(await screen.findByRole('option', { name: 'Automatic', exact: true })); + fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); + await waitFor(() => expect(f.run).toHaveBeenCalled()); + expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_model: '', compact_provider: '' }); + }); + + it('validates thresholds and never applies settings to an active session', async () => { + const f = fixture(); + f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: 'original', compact_provider: 'provider', compact_percent: 60 }); + f.render(<Compaction {...f.props} />); + await screen.findByText('Custom · 60%'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + const percent = screen.getByRole('spinbutton', { name: 'Context window percentage' }); + for (const value of ['', '0', '9', '91', '12.5']) { + fireEvent.change(percent, { target: { value } }); + expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); + expect(screen.getByText('Use a whole-number percentage from 10 to 90, or choose Automatic.')).toBeDefined(); + } + fireEvent.change(percent, { target: { value: '65' } }); + expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', false); + act(() => { f.root.active_turns = { root: 'turn' } as unknown as RootSnapshot['active_turns']; }); + fireEvent.change(percent, { target: { value: '66' } }); + expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); + expect(screen.getByRole('button', { name: 'Compact now' })).toHaveProperty('disabled', true); + expect(f.client.configuration.update).not.toHaveBeenCalled(); + expect(f.run).not.toHaveBeenCalled(); + }); +}); + +it('saves only the inspector threshold edit, including Automatic reset', async () => { + const f = fixture(); + f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: 'original', compact_provider: 'provider', compact_percent: 60 }); + f.render(<Compaction {...f.props} />); + await screen.findByText('Custom · 60%'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: '65' } }); + fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); + await waitFor(() => expect(f.run).toHaveBeenCalledTimes(1)); + expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_percent: 65 }); + await waitFor(() => expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', false)); + fireEvent.click(screen.getByRole('combobox', { name: 'Compaction timing' })); + await userEvent.click(await screen.findByRole('option', { name: 'Automatic · 50%', exact: true })); + fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); + await waitFor(() => expect(f.run).toHaveBeenCalledTimes(2)); + expect(f.client.configuration.update).toHaveBeenLastCalledWith({ revision: '1', compact_percent: 0 }); +}); + +it('disables inspector defaults while a save is pending', async () => { + const f = fixture(); + f.client.configuration.update.mockImplementationOnce(() => new Promise(() => {})); + f.render(<Compaction {...f.props} />); + await screen.findByText('Custom · original · provider'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); + await waitFor(() => expect(f.client.configuration.update).toHaveBeenCalled()); + expect(screen.getByRole('combobox', { name: 'Summary model mode' })).toHaveProperty('disabled', true); + expect(screen.getByRole('button', { name: 'Custom summary model' })).toHaveProperty('disabled', true); + expect(screen.getByRole('button', { name: 'Refresh compaction defaults' })).toHaveProperty('disabled', true); + expect(f.run).not.toHaveBeenCalled(); +}); + +it('preserves a compaction draft when disconnect cleanup removes configuration data', async () => { + const f = fixture(); + const view = f.render(<Compaction {...f.props} />); + await screen.findByText('Custom · original · provider'); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + fireEvent.click(await screen.findByRole('option', { name: 'my-model · provider' })); + act(() => { + f.queries.removeQueries({ queryKey: ['inspector-compaction-config', 'runtime'] }); + }); + view.rerender(f.wrapper(<Compaction {...f.props} connected={false} />)); + expect(screen.getByText('Custom · my-model · provider')).toBeDefined(); + expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); + expect(f.client.configuration.update).not.toHaveBeenCalled(); +}); diff --git a/packages/app/test/multi-host-discovery.test.tsx b/packages/app/test/multi-host-discovery.test.tsx index af6b583b7..6d31ef345 100644 --- a/packages/app/test/multi-host-discovery.test.tsx +++ b/packages/app/test/multi-host-discovery.test.tsx @@ -88,7 +88,7 @@ it('observes catalogs and loads all-status pages only while search is open, rout expect(f.local.client.session).not.toHaveBeenCalled(); expect(f.remote.client.session).not.toHaveBeenCalled(); }); -it('keeps pagination and search failures independent, and filters hosts without hydrating roots', async () => { +it('keeps pagination and search failures independent across hosts without hydrating roots', async () => { const f = fixture(); f.render(<SessionSearchDialog open onOpenChange={() => {}} finalFocus={false} />); await screen.findByRole('link', { name: 'Kuzco landing · Kuzco · /repo' }); @@ -103,10 +103,6 @@ it('keeps pagination and search failures independent, and filters hosts without expect(screen.getByRole('link', { name: 'Kuzco match · Kuzco · /repo' })).toBeTruthy(); expect(f.remote.search).toHaveBeenCalledTimes(3); expect(f.local.search.mock.lastCall?.[0]).toEqual({ search: 'match', status: 'all', cursor: { revision: '1', offset: 'local-runtime-cursor' }, limit: 64, max_bytes: 256 << 10 }); - fireEvent.click(screen.getByRole('combobox', { name: 'Search host' })); - const option = await screen.findByRole('option', { name: 'Kuzco' }); fireEvent.pointerDown(option); fireEvent.click(option); - await waitFor(() => expect(screen.queryByRole('region', { name: 'Local search results' })).toBeNull()); - expect(screen.getByRole('link', { name: 'Kuzco match · Kuzco · /repo' })).toBeTruthy(); expect(f.local.client.session).not.toHaveBeenCalled(); expect(f.remote.client.session).not.toHaveBeenCalled(); }); diff --git a/packages/app/test/session-sidebar.test.tsx b/packages/app/test/session-sidebar.test.tsx index f9668fdb9..b66eba3f5 100644 --- a/packages/app/test/session-sidebar.test.tsx +++ b/packages/app/test/session-sidebar.test.tsx @@ -1,56 +1,206 @@ -import type { ReactNode } from 'react'; -import type { LocalRuntimeStatus } from '../src/platform'; -import { fireEvent, render, screen } from '@testing-library/react'; -import { expect, it, vi } from 'vitest'; +import { useRef, useState, type ReactNode } from 'react'; +import { act, fireEvent, render, screen, within, waitFor } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { beforeEach, expect, it, vi } from 'vitest'; import { SessionSidebar } from '../src/session-sidebar'; import { emptySidebarState } from '../src/sidebar-state'; +import type { HostConnection } from '../src/hosts'; +import type { SessionListView, SessionListSnapshot } from '@whip/sdk/state'; -vi.hoisted(() => { globalThis.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} }; }); - -const app = vi.hoisted(() => ({ hosts: [] as { id: string; name: string; state: string; endpoint: string; localRuntime?: LocalRuntimeStatus }[] })); +const fixture = vi.hoisted(() => { + globalThis.ResizeObserver = class { observe() {} unobserve() {} disconnect() {} }; + return { + app: { hosts: [] as HostConnection[] }, pathname: '/', + runtime: { queries: { invalidateQueries: vi.fn() }, tabs: { preferred: vi.fn(), open: vi.fn() }, connections: { connect: vi.fn().mockResolvedValue(undefined) } }, + scrollToIndex: vi.fn(), archive: vi.fn(), + }; +}); +Object.defineProperty(window, 'matchMedia', { configurable: true, value: () => ({ matches: false, addEventListener() {}, removeEventListener() {} }) }); vi.mock('../src/context', () => ({ - useAppState: () => app, - useRuntime: () => ({}), + useAppState: () => fixture.app, useRuntime: () => fixture.runtime, useSessionTabs: () => ({}), })); +vi.mock('../src/session-actions', () => ({ useSessionActions: () => ({ items: () => [], archive: fixture.archive, prepare: vi.fn() }) })); +vi.mock('@whip/ui/workspace-tabs', () => ({ WorkspaceExternalSource: ({ children }: { children(props: object): ReactNode }) => children({}) })); vi.mock('@tanstack/react-router', () => ({ - Link: ({ children }: { children: ReactNode }) => <a>{children}</a>, - useNavigate: () => vi.fn(), + Link: ({ children, to, params, search, preload, state, ...props }: { children: ReactNode; to: string; params?: { runtimeId: string; rootId: string }; search?: object; preload?: boolean; state?: object }) => + <a {...props} href={params ? '/h/' + params.runtimeId + '/s/' + params.rootId : to}>{children}</a>, + useNavigate: () => vi.fn(), useLocation: () => ({ pathname: fixture.pathname }), })); +vi.mock('@tanstack/react-virtual', () => ({ useVirtualizer: (options: { count: number; getItemKey(index: number): string; estimateSize(index: number): number }) => { + const current = useRef(options); + current.current = options; + // TanStack retains one instance across renders, including route-only navigation. + const virtualizer = useRef({ + getVirtualItems: () => Array.from({ length: current.current.count }, (_, index) => ({ index, key: current.current.getItemKey(index), size: current.current.estimateSize(index), start: index * 36, end: (index + 1) * 36 })), + getTotalSize: () => current.current.count * 36, measure() {}, scrollToOffset() {}, scrollToIndex: fixture.scrollToIndex, + }); + return virtualizer.current; +} })); + +beforeEach(() => { fixture.pathname = '/'; }); -const local = { id: 'local', name: 'Local', state: 'closed', endpoint: 'http://localhost' }; -const remote = { id: 'remote', name: 'Remote', state: 'closed', endpoint: 'https://remote.example' }; -const sidebar = () => <SessionSidebar state={emptySidebarState()} setState={vi.fn()} - onSearch={vi.fn()} onConnect={vi.fn()} onNavigate={vi.fn()} />; +const local = { id: 'local', name: 'Local', local: true, state: 'closed', endpoint: 'http://localhost' } as HostConnection; +const remote = { id: 'remote', name: 'mm', local: false, state: 'closed', endpoint: 'https://remote.example' } as HostConnection; +const session = (id: string, cwd: string, updated_at = '2026-09-27T12:00:00Z') => ({ id, cwd, updated_at, pinned: false, archived: false, title: id, kind: 'root', model: '', provider: '', truncated: false }); +function loaded(host: HostConnection, items: ReturnType<typeof session>[], has_more = false) { + let snapshot: SessionListSnapshot = { status: 'live', truncated: false, page: { items, revision: '1', has_more } }; + const listeners = new Set<() => void>(); + const list = { getSnapshot: () => snapshot, subscribe: (listener: () => void) => { listeners.add(listener); return () => listeners.delete(listener); }, loadMore: vi.fn().mockResolvedValue(undefined), refresh: vi.fn().mockResolvedValue(undefined) }; + const summaries = vi.fn().mockResolvedValue({ items: [] }); + return { + host: { ...host, runtimeId: host.id, state: 'connected', list: list as unknown as SessionListView, + client: { getSnapshot: () => ({ info: { negotiated_capabilities: ['session_summaries'] } }), sessions: { summaries }, onEvent: () => () => {} } } as unknown as HostConnection, + list, summaries, listeners, + update(items: ReturnType<typeof session>[]) { snapshot = { ...snapshot, page: { ...snapshot.page!, items } }; listeners.forEach(listener => listener()); }, + }; +} +function Sidebar() { + const [state, setState] = useState(emptySidebarState); + return <SessionSidebar state={state} setState={setState} onSearch={vi.fn()} onConnect={vi.fn()} onNavigate={vi.fn()} />; +} +const sidebar = () => <QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false } } })}><Sidebar /></QueryClientProvider>; -it('omits the single-server heading without hiding its content or server management', () => { - app.hosts = [local]; +it('omits host accordions without hiding connections or server management', () => { + fixture.app.hosts = [local, remote]; render(sidebar()); + expect(screen.getByRole('region', { name: 'Projects' })).toBeTruthy(); + expect(screen.queryByText('Projects')).toBeNull(); expect(screen.queryByRole('button', { name: /^Local\s*Offline$/ })).toBeNull(); expect(screen.getByRole('button', { name: 'Connect Local' })).toBeTruthy(); + expect(screen.getByRole('button', { name: 'Connect mm' })).toBeTruthy(); expect(screen.getByRole('button', { name: 'Manage servers' })).toBeTruthy(); }); -it.each([false, true])('omits redundant local setup actions while keeping remote connections available (repairRequired=%s)', repairRequired => { - app.hosts = [{ ...local, localRuntime: { state: 'missing', home: '/tmp/whip-test', message: 'No installation.', canInstall: true, repairRequired } }, remote]; +it.each([false, true])('keeps local setup out of project navigation (repairRequired=%s)', repairRequired => { + fixture.app.hosts = [{ ...local, localRuntime: { state: 'missing', home: '/tmp/whip-test', message: 'No installation.', canInstall: true, repairRequired } }, remote]; render(sidebar()); expect(screen.queryByRole('button', { name: 'Set up this Mac' })).toBeNull(); expect(screen.queryByRole('button', { name: 'Repair this Mac' })).toBeNull(); expect(screen.queryByRole('button', { name: 'Connect Local' })).toBeNull(); - expect(screen.getByRole('button', { name: 'Connect Remote' })).toBeTruthy(); - expect(screen.getByRole('button', { name: 'Manage servers' })).toBeTruthy(); + expect(screen.getByRole('button', { name: 'Connect mm' })).toBeTruthy(); }); -it('keeps multiple servers collapsible and reveals a collapsed server when it becomes the only one', () => { - app.hosts = [local, remote]; - const { rerender } = render(sidebar()); - const heading = screen.getByRole('button', { name: /^Local\s*Offline$/ }); - expect(screen.getByRole('button', { name: /^Remote\s*Offline$/ })).toBeTruthy(); - fireEvent.click(heading); - expect(heading.getAttribute('aria-expanded')).toBe('false'); - expect(screen.queryByRole('button', { name: 'Connect Local' })).toBeNull(); - expect(screen.getByRole('button', { name: 'Connect Remote' })).toBeTruthy(); - app.hosts = [local]; - rerender(sidebar()); - expect(screen.queryByRole('button', { name: /^Local\s*Offline$/ })).toBeNull(); - expect(screen.getByRole('button', { name: 'Connect Local' })).toBeTruthy(); +it('interleaves directories, isolates identical paths/ids, and releases catalog observers', async () => { + const a = loaded(local, [session('same', '/repo', '2026-09-27T13:00:00Z'), session('old', '/older', '2026-09-26T00:00:00Z')]); + const b = loaded(remote, [session('same', '/repo')]); + fixture.app.hosts = [a.host, b.host]; + const view = render(sidebar()); + const directories = () => [...view.container.querySelectorAll<HTMLElement>('[data-sidebar-directory]')]; + expect(directories().map(row => [row.dataset.sidebarRuntime, row.dataset.sidebarDirectory])).toEqual([['local', '/repo'], ['remote', '/repo'], ['local', '/older']]); + expect(screen.getByRole('button', { name: 'mm · Connected · /repo' })).toBeTruthy(); + for (const directory of directories()) { + expect(directory.querySelector('.lucide-folder, .lucide-folder-open, .lucide-globe')).toBeNull(); + expect(directory.querySelector('[data-directory-caret]')).toBeTruthy(); + } + expect(screen.queryByRole('button', { name: 'Local · Connected · /repo' })).toBeNull(); + expect(view.container.querySelectorAll('a[href$="/s/same"]')).toHaveLength(2); + const remoteSession = view.container.querySelector<HTMLElement>('[data-sidebar-session="same"][data-sidebar-runtime="remote"]')!; + fireEvent.click(within(remoteSession).getByRole('button', { name: 'Archive same' })); + expect(fixture.archive).toHaveBeenLastCalledWith({ runtimeId: 'remote', rootId: 'same', title: 'same', archived: false }, true); + await waitFor(() => expect(a.summaries).toHaveBeenCalled()); + expect(a.summaries.mock.calls[0]?.[0]).toEqual(['old', 'same']); + expect(b.summaries.mock.calls[0]?.[0]).toEqual(['same']); + fireEvent.click(within(directories()[1]!).getByRole('button', { name: '/repo', exact: true })); + expect(view.container.querySelector('a[href="/h/remote/s/same"]')).toBeNull(); + expect(view.container.querySelector('a[href="/h/local/s/same"]')).not.toBeNull(); + act(() => b.update([session('same', '/repo', '2026-09-28T00:00:00Z')])); + expect(directories()[0]?.dataset.sidebarRuntime).toBe('remote'); + expect(within(directories()[0]!).getByRole('button', { name: '/repo', exact: true }).getAttribute('aria-expanded')).toBe('false'); + view.unmount(); + expect(a.listeners.size + b.listeners.size).toBe(0); +}); + +it('reveals on route-only navigation with stable catalogs and virtualizer', () => { + const a = loaded(local, [session('same', '/repo')]); + const b = loaded(remote, [session('same', '/repo')]); + fixture.app.hosts = [a.host, b.host]; + fixture.pathname = '/'; + const view = render(sidebar()); + const directory = view.container.querySelector<HTMLElement>('[data-sidebar-directory][data-sidebar-runtime="remote"]')!; + fireEvent.click(within(directory).getByRole('button', { name: '/repo', exact: true })); + fixture.scrollToIndex.mockClear(); + fixture.pathname = '/h/remote/s/same'; + view.rerender(sidebar()); + expect(view.container.querySelector('a[href="/h/remote/s/same"]')).not.toBeNull(); + expect(fixture.scrollToIndex).toHaveBeenCalledOnce(); + expect(within(directory).getByRole('button', { name: '/repo', exact: true }).getAttribute('aria-expanded')).toBe('true'); + fixture.scrollToIndex.mockClear(); + fixture.pathname = '/h/local/s/same'; + view.rerender(sidebar()); + expect(fixture.scrollToIndex).toHaveBeenCalledOnce(); + fixture.pathname = '/'; +}); + +it('exposes untruncated connection identity for duplicate host names and paths', async () => { + const a = loaded(remote, [session('same', '/repo')]); + const b = loaded({ ...remote, id: 'remote-2', endpoint: 'https://another.example' }, [session('same', '/repo')]); + fixture.app.hosts = [a.host, b.host]; + render(sidebar()); + fireEvent.click(screen.getByRole('button', { name: 'mm · remote-2 · Connected · /repo', exact: true })); + const details = await screen.findByRole('dialog', { name: /^mm · remote-2 Connected/ }); + expect(within(details).getByText('https://another.example', { exact: true })).toBeTruthy(); + expect(within(details).getByText('/repo', { exact: true })).toBeTruthy(); +}); + +it('keeps host details compact without repeating the address and retains reconnect actions', async () => { + const a = loaded({ ...remote, endpoint: 'mm' }, [session('same', '/repo')]); + fixture.app.hosts = [a.host]; + const view = render(sidebar()); + fireEvent.click(screen.getByRole('button', { name: 'mm · Connected · /repo', exact: true })); + const details = await screen.findByRole('dialog', { name: 'mm Connected', exact: true }); + expect(within(details).getAllByText('mm', { exact: true })).toHaveLength(1); + expect(within(details).getByText('/repo', { exact: true })).toBeTruthy(); + expect(within(details).queryByRole('button', { name: 'Reconnect mm' })).toBeNull(); + expect(within(details).getByRole('button', { name: 'Manage servers' })).toBeTruthy(); + fixture.app.hosts = [{ ...a.host, state: 'reconnecting', error: 'Connection lost' }]; + view.rerender(sidebar()); + expect(within(details).getByText('Reconnecting', { exact: true })).toBeTruthy(); + expect(within(details).getByRole('status').textContent).toBe('Connection lost'); + expect(within(details).getByRole('button', { name: 'Reconnect mm' }).hasAttribute('disabled')).toBe(true); + fixture.app.hosts = [{ ...a.host, state: 'closed' }]; + view.rerender(sidebar()); + fireEvent.click(within(details).getByRole('button', { name: 'Reconnect mm' })); + expect(fixture.runtime.connections.connect).toHaveBeenLastCalledWith('remote'); +}); + +it('reveals an older routed session only in its source host, never on catalog polling', () => { + const a = loaded(local, [session('same', '/repo')]); + const b = loaded(remote, Array.from({ length: 16 }, (_, i) => session('remote-' + i, '/repo'))); + fixture.app.hosts = [a.host, b.host]; + fixture.pathname = '/h/remote/s/remote-15'; + const view = render(sidebar()); + expect(view.container.querySelectorAll('[data-sidebar-session][data-sidebar-runtime="remote"]')).toHaveLength(16); + expect(view.container.querySelectorAll('[data-sidebar-session][data-sidebar-runtime="local"]')).toHaveLength(1); + expect(view.container.querySelector('a[href="/h/remote/s/remote-15"]')?.getAttribute('aria-current')).toBe('page'); + const directory = view.container.querySelector('[data-sidebar-directory][data-sidebar-runtime="remote"]')!; + fireEvent.click(within(directory as HTMLElement).getByRole('button', { name: '/repo', exact: true })); + act(() => b.update([session('remote-15', '/repo')])); + expect(view.container.querySelector('a[href="/h/remote/s/remote-15"]')).toBeNull(); + fixture.pathname = '/'; +}); + +it('keeps seven/More/Less per host, stale rows on transport loss, and clears detached rows', async () => { + const a = loaded(local, Array.from({ length: 15 }, (_, i) => session('local-' + i, '/repo'))); + const b = loaded(remote, Array.from({ length: 15 }, (_, i) => session('remote-' + i, '/repo')), true); + fixture.app.hosts = [a.host, b.host]; + const view = render(sidebar()); + const sessions = (id: string) => view.container.querySelectorAll('[data-sidebar-session][data-sidebar-runtime="' + id + '"]'); + expect(sessions('local')).toHaveLength(7); + expect(sessions('remote')).toHaveLength(7); + const more = () => view.container.querySelector<HTMLButtonElement>('button[data-sidebar-runtime="remote"][aria-label="More sessions in /repo"]')!; + fireEvent.click(more()); expect(sessions('remote')).toHaveLength(14); + fireEvent.click(more()); expect(sessions('remote')).toHaveLength(15); + fireEvent.click(screen.getByRole('button', { name: 'Less sessions in /repo' })); + expect(sessions('remote')).toHaveLength(7); + expect(sessions('local')).toHaveLength(7); + fireEvent.click(screen.getByRole('button', { name: 'Load more sessions · mm' })); + expect(b.list.loadMore).toHaveBeenCalledOnce(); expect(a.list.loadMore).not.toHaveBeenCalled(); + fixture.app.hosts = [a.host, { ...b.host, state: 'reconnecting' }]; + view.rerender(sidebar()); + expect(screen.getByRole('button', { name: 'mm · Reconnecting · /repo' })).toBeTruthy(); + expect(sessions('remote')).toHaveLength(7); + fixture.app.hosts = [a.host, remote]; + view.rerender(sidebar()); + expect(sessions('remote')).toHaveLength(0); + expect(screen.getByRole('button', { name: 'Connect mm' })).toBeTruthy(); }); diff --git a/packages/app/test/session-top-bar.test.tsx b/packages/app/test/session-top-bar.test.tsx index a37601048..ff403511c 100644 --- a/packages/app/test/session-top-bar.test.tsx +++ b/packages/app/test/session-top-bar.test.tsx @@ -111,11 +111,9 @@ it('shows one current status in the bar without a duplicate agent dock', () => { expect(screen.getByRole('status').textContent).toBe('Reconnecting · activity updates paused'); }); -it('preserves the activity motion control and hides session-only controls for New Chat', () => { +it('hides session-only controls for New Chat', () => { const view = render(<ThemeProvider><UIProvider><SessionTopBar host="Local" cwd="/whip" agentName="Root" kind="repl" activity={<CurrentActivity status={{ text: 'Working', active: true }} connected onDetails={vi.fn()} />} /></UIProvider></ThemeProvider>); - fireEvent.click(screen.getByRole('button', { name: 'Pause activity animation' })); - expect(screen.getByRole('button', { name: 'Use system motion setting' })).toBeDefined(); view.rerender(<ThemeProvider><UIProvider><SessionTopBar host="Choose a host" kind="new" /></UIProvider></ThemeProvider>); expect(screen.getByText('Not started')).toBeDefined(); expect(screen.queryByRole('group', { name: 'Session view' })).toBeNull(); diff --git a/packages/app/test/settings-agents.test.tsx b/packages/app/test/settings-agents.test.tsx index 62201f199..09bc68823 100644 --- a/packages/app/test/settings-agents.test.tsx +++ b/packages/app/test/settings-agents.test.tsx @@ -15,7 +15,7 @@ afterEach(() => vi.unstubAllGlobals()); const coding: Definition = { id: 'coding', instructions: { persona: 'You are a coding agent.', rules: 'Rules.', project_files: ['CLAUDE.md'], skill_discovery: true, standing_instructions: true }, - modules: ['context', 'files', 'shell', 'agents', 'user'], capabilities: ['read', 'write', 'shell', 'mcp'], + modules: ['context', 'files', 'shell', 'browser', 'computer', 'models', 'agents', 'messages', 'mcp', 'state', 'artifacts', 'schedules', 'permissions', 'user'], capabilities: ['read', 'write', 'shell', 'browser', 'computer', 'mcp'], model: { model: '', provider: '', effort: '' }, compaction: { model: '', provider: '', threshold: 0 }, mcp: { servers: null }, tools: null, output: null, children: {}, surface: { auto_title: true, goal_loop: true }, hooks: null, }; @@ -41,13 +41,20 @@ it('lists built-in and registered agents and registers a new data-only definitio const f = fixture(); f.render(); const rows = await screen.findAllByRole('listitem', {}, { timeout: 3000 }); expect(rows.map(row => row.textContent)).toEqual([expect.stringContaining('codingBuilt in'), expect.stringContaining('support-triageRegistered by app · revision bbbbbbbbbbbb')]); + fireEvent.click(screen.getByRole('button', { name: 'New agent' })); + await screen.findByRole('dialog', { name: 'New agent' }); + await waitFor(() => expect(globalThis.document.activeElement).toBe(screen.getByLabelText('Agent Name'))); const modules = await screen.findByRole('group', { name: 'Host modules' }, { timeout: 3000 }); await within(modules).findByRole('checkbox', { name: 'shell' }, { timeout: 3000 }); const capabilities = screen.getByRole('group', { name: 'Capabilities' }); - fireEvent.change(screen.getByLabelText('Agent id'), { target: { value: 'release-notes' } }); + fireEvent.change(screen.getByLabelText('Agent Name'), { target: { value: 'release-notes' } }); fireEvent.change(screen.getByLabelText('Persona'), { target: { value: 'You write release notes.' } }); fireEvent.change(screen.getByLabelText('Rules'), { target: { value: 'Operating rules:\n- Cite commits.' } }); + expect(screen.queryByLabelText('Project files')).toBeNull(); + fireEvent.click(screen.getByRole('button', { name: 'More options' })); fireEvent.change(screen.getByLabelText('Project files'), { target: { value: 'CHANGELOG.md, docs/releases.md' } }); + fireEvent.click(screen.getByRole('switch', { name: 'Goal loop' })); + fireEvent.click(screen.getByRole('button', { name: 'More options' })); fireEvent.click(within(modules).getByRole('checkbox', { name: 'context' })); fireEvent.click(within(modules).getByRole('checkbox', { name: 'files' })); fireEvent.click(within(capabilities).getByRole('checkbox', { name: 'read' })); @@ -61,20 +68,26 @@ it('lists built-in and registered agents and registers a new data-only definitio expect(document.capabilities).toEqual(['read']); expect(document.tools).toBeNull(); expect(document.hooks).toBeNull(); - expect(document.surface).toEqual({ auto_title: true, goal_loop: false }); + expect(document.surface).toEqual({ auto_title: true, goal_loop: true }); await waitFor(() => expect(f.list).toHaveBeenCalledTimes(2)); + // The modal dialog hides the background list; close it before reading the refreshed rows. + fireEvent.click(screen.getByRole('button', { name: 'Close' })); + await waitFor(() => expect(screen.queryByRole('dialog')).toBeNull()); await waitFor(() => expect(within(screen.getByRole('list', { name: 'Agent definitions' })).getAllByRole('listitem')).toHaveLength(3)); }); it('validates locally before registering and shows the daemon rejection otherwise', async () => { const f = fixture(); f.render(); + fireEvent.click(await screen.findByRole('button', { name: 'New agent' })); + await screen.findByRole('dialog', { name: 'New agent' }); + await waitFor(() => expect(globalThis.document.activeElement).toBe(screen.getByLabelText('Agent Name'))); const modules = await screen.findByRole('group', { name: 'Host modules' }, { timeout: 3000 }); await within(modules).findByRole('checkbox', { name: 'shell' }, { timeout: 3000 }); - fireEvent.change(screen.getByLabelText('Agent id'), { target: { value: 'Bad Id' } }); + fireEvent.change(screen.getByLabelText('Agent Name'), { target: { value: 'Bad Id' } }); fireEvent.click(within(modules).getByRole('checkbox', { name: 'context' })); fireEvent.click(screen.getByRole('button', { name: 'Register agent' })); - expect(await screen.findByText(/Use a lowercase id/)).toBeTruthy(); - fireEvent.change(screen.getByLabelText('Agent id'), { target: { value: 'coding' } }); + expect(await screen.findByText(/Use a lowercase name/)).toBeTruthy(); + fireEvent.change(screen.getByLabelText('Agent Name'), { target: { value: 'coding' } }); fireEvent.click(screen.getByRole('button', { name: 'Register agent' })); expect(await screen.findByText(/reserved for a built-in definition/)).toBeTruthy(); expect(f.register).toHaveBeenCalledOnce(); @@ -84,16 +97,21 @@ it('opens a registered agent for editing and copies a built-in under a new id', const f = fixture(); f.render(); const rows = await screen.findAllByRole('listitem', {}, { timeout: 3000 }); fireEvent.click(within(rows[1]).getByRole('button', { name: 'Edit' })); - await screen.findByRole('heading', { name: 'Edit support-triage' }); - expect((screen.getByLabelText('Agent id') as HTMLInputElement).value).toBe('support-triage'); + await screen.findByRole('dialog', { name: 'Edit support-triage' }); + expect((screen.getByLabelText('Agent Name') as HTMLInputElement).value).toBe('support-triage'); + await waitFor(() => expect(globalThis.document.activeElement).toBe(screen.getByLabelText('Agent Name'))); expect((screen.getByLabelText('Persona') as HTMLTextAreaElement).value).toBe('You triage tickets.'); const modules = await screen.findByRole('group', { name: 'Host modules' }, { timeout: 3000 }); await within(modules).findByRole('checkbox', { name: 'shell' }, { timeout: 3000 }); expect(within(modules).getByRole('checkbox', { name: 'files' }).getAttribute('aria-checked')).toBe('true'); expect(within(modules).getByRole('checkbox', { name: 'shell' }).getAttribute('aria-checked')).toBe('false'); + // Close the edit dialog before opening a copy from the list; the modal hides the background rows. + fireEvent.click(screen.getByRole('button', { name: 'Close' })); + await waitFor(() => expect(screen.queryByRole('dialog')).toBeNull()); fireEvent.click(within(rows[0]).getByRole('button', { name: 'Copy to new agent' })); - await screen.findByRole('heading', { name: 'Edit coding-custom' }); - expect((screen.getByLabelText('Agent id') as HTMLInputElement).value).toBe('coding-custom'); + await screen.findByRole('dialog', { name: 'Edit coding-custom' }); + expect((screen.getByLabelText('Agent Name') as HTMLInputElement).value).toBe('coding-custom'); + await waitFor(() => expect(globalThis.document.activeElement).toBe(screen.getByLabelText('Agent Name'))); expect(f.get).toHaveBeenCalledWith('support-triage', 'b'.repeat(64)); expect(f.get).toHaveBeenCalledWith('coding', undefined); }); diff --git a/packages/app/test/settings-configuration.test.tsx b/packages/app/test/settings-configuration.test.tsx index 669877821..4e989172f 100644 --- a/packages/app/test/settings-configuration.test.tsx +++ b/packages/app/test/settings-configuration.test.tsx @@ -1,5 +1,5 @@ import userEvent from '@testing-library/user-event'; -import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ThemeProvider, UIProvider } from '@whip/ui'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; @@ -26,7 +26,7 @@ function fixture() { server = { ...server, ...patch, revision: 'v2' }; return server; }); - const client = { getSnapshot: () => ({ state: 'connected', info: { runtime_id: 'host-a' } }), configuration: { get, update }, providers: { catalogs: vi.fn(async () => ({ result: { models: {}, providers: {}, catalogs: { openrouter: { models: ['model-a', 'model-b', 'host-a-draft', 'new-host-b-model', 'temporary-edit'].map(id => ({ id, reasoning_efforts: ['low', 'high'] })) }, subscription: { models: [{ id: 'model-a', reasoning_efforts: ['low', 'ultra'] }, { id: 'no-reasoning', reasoning_efforts: [] }] } } } })) } } as unknown as WhipClient; + const client = { getSnapshot: () => ({ state: 'connected', info: { runtime_id: 'host-a' } }), configuration: { get, update }, providers: { catalogs: vi.fn(async () => ({ result: { models: {}, providers: { openrouter: { available: true }, subscription: { available: true }, offline: { available: false }, unknown: {} }, catalogs: { offline: { models: [{ id: 'offline-model' }] }, unknown: { models: [{ id: 'unknown-model' }] }, openrouter: { models: ['model-a', 'model-b', 'host-a-draft', 'new-host-b-model', 'temporary-edit'].map(id => ({ id, reasoning_efforts: ['low', 'high'] })) }, subscription: { models: [{ id: 'model-a', reasoning_efforts: ['low', 'ultra'] }, { id: 'no-reasoning', reasoning_efforts: [] }] } } } })) } } as unknown as WhipClient; const state = { commands: [] }; const runtime = { queries, report: vi.fn(), getSnapshot: () => state, subscribe: () => () => {} } as unknown as AppRuntime; function wrapper(children: ReactNode) { return <RuntimeContext.Provider value={runtime}><ThemeProvider initialTheme="light"><UIProvider><QueryClientProvider client={queries}>{children}</QueryClientProvider></UIProvider></ThemeProvider></RuntimeContext.Provider>; } @@ -54,7 +54,7 @@ it('saves only execution-owned fields and retains model defaults from the host', fireEvent.change(await screen.findByLabelText('Retry limit'), { target: { value: '4' } }); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); - expect(f.update).toHaveBeenCalledExactlyOnceWith({ revision: 'v1', default_execution_engine: 'starlark', compact_model: 'small-a', compact_provider: 'inference', compact_percent: 75, goal_max_rounds: 8, max_retries: 4, import_claude: true, import_codex: false }, { signal: expect.any(AbortSignal) }); + expect(f.update).toHaveBeenCalledExactlyOnceWith({ revision: 'v1', default_execution_engine: 'starlark', goal_max_rounds: 8, max_retries: 4, import_claude: true, import_codex: false }, { signal: expect.any(AbortSignal) }); expect((f.queries.getQueryData(['runtime-configuration', 'host-a']) as RuntimeConfiguration).default_model).toBe('model-a'); }); @@ -171,7 +171,7 @@ it('classifies invalid defaults as validation and preserves the draft without wr const f = fixture(); const view = f.render('execution'); fireEvent.change(await screen.findByLabelText('Retry limit'), { target: { value: '-1' } }); fireEvent.submit(view.container.querySelector('form')!); - await screen.findByText('Use whole numbers: compaction from 0 to 100%, and non-negative goal rounds and retries.'); + await screen.findByText('Use non-negative whole numbers for goal rounds and retries.'); expect(view.container.querySelector('[data-error-type="validation"]')).not.toBeNull(); expect(f.update).not.toHaveBeenCalled(); expect(f.runtime.report).not.toHaveBeenCalled(); @@ -263,3 +263,101 @@ it('disables permission changes while disconnected or saving', async () => { await waitFor(() => expect(f.update).toHaveBeenCalledTimes(1)); expect(screen.getByRole('button', { name: 'Default permission level' })).toHaveProperty('disabled', true); }); + +async function chooseCompactionMode(label: string, option: string) { + fireEvent.click(screen.getByRole('combobox', { name: label, exact: true })); + await userEvent.click(await screen.findByRole('option', { name: option, exact: true })); +} + +it('keeps automatic compaction simple and only loads connected custom routes on demand', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_model: '', compact_provider: '', compact_percent: 0 }); + f.render('execution'); + const group = await screen.findByRole('region', { name: 'Context compaction' }); + expect(within(group).getByText('Automatic · conversation model and provider')).toBeDefined(); + expect(within(group).getByText('Automatic · 50%')).toBeDefined(); + expect(within(group).getByText('Older active context is summarized. Full conversation history remains available.')).toBeDefined(); + expect(within(group).queryByRole('combobox')).toBeNull(); + expect(f.client.providers.catalogs).not.toHaveBeenCalled(); + fireEvent.click(within(group).getByRole('button', { name: 'Advanced compaction settings' })); + expect(f.client.providers.catalogs).not.toHaveBeenCalled(); + await chooseCompactionMode('Summary model mode', 'Custom'); + fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + expect(await screen.findByRole('option', { name: 'model-a · subscription' })).toBeDefined(); + expect(screen.queryByRole('option', { name: 'offline-model · offline' })).toBeNull(); + expect(screen.queryByRole('option', { name: 'unknown-model · unknown' })).toBeNull(); + fireEvent.click(screen.getByRole('option', { name: 'model-a · subscription' })); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: 'model-a', compact_provider: 'subscription' }); + expect(screen.getByText('Custom · model-a · subscription')).toBeDefined(); + expect(screen.queryByRole('textbox', { name: /provider/i })).toBeNull(); +}); + +it('retains a saved deepseek override until Automatic explicitly clears both fields', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_model: 'deepseek-v3.2', compact_provider: 'inference' }); + f.render('execution'); + expect(await screen.findByText('Custom · deepseek-v3.2 · inference')).toBeDefined(); + expect(screen.getByRole('button', { name: 'Save host defaults' })).toHaveProperty('disabled', true); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + expect(screen.getByRole('combobox', { name: 'Summary model mode' }).textContent).toBe('Custom'); + await chooseCompactionMode('Summary model mode', 'Automatic'); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_percent'); +}); + +it.each(['', '0', '9', '91', '10.5'])('rejects custom threshold %j without writing', async threshold => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); + const view = f.render('execution'); + fireEvent.click(await screen.findByRole('button', { name: 'Advanced compaction settings' })); + await chooseCompactionMode('Compaction timing', 'Custom'); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: threshold } }); + fireEvent.submit(view.container.querySelector('form')!); + await waitFor(() => expect(view.container.querySelector('[data-error-type="validation"]')).not.toBeNull()); + expect(f.update).not.toHaveBeenCalled(); + expect(screen.getByRole('spinbutton', { name: 'Context window percentage' }).getAttribute('aria-invalid')).toBe('true'); +}); + +it.each([10, 90])('saves custom threshold %i and can reset to Automatic', async threshold => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); + f.render('execution'); + fireEvent.click(await screen.findByRole('button', { name: 'Advanced compaction settings' })); + await chooseCompactionMode('Compaction timing', 'Custom'); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: String(threshold) } }); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0].compact_percent).toBe(threshold); + await chooseCompactionMode('Compaction timing', 'Automatic · 50%'); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await waitFor(() => expect(f.update).toHaveBeenCalledTimes(2)); + expect(f.update.mock.calls[1]![0].compact_percent).toBe(0); +}); + +it.each([[5, 10], [95, 90], [-2, 10]])('shows the effective legacy threshold for %i without rewriting it', async (raw, effective) => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: raw }); + const view = f.render('execution'); + expect(await screen.findByText('Custom · ' + effective + '%')).toBeDefined(); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + expect(view.container.querySelector('form')).toHaveProperty('noValidate', true); + expect((screen.getByRole('spinbutton', { name: 'Context window percentage' }) as HTMLInputElement).checkValidity()).toBe(false); + expect(screen.getByText('Saved value: ' + raw + '%. The effective threshold is ' + effective + '%; saving other settings keeps the saved value.')).toBeDefined(); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Retry limit' }), { target: { value: '4' } }); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_percent'); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_model'); + expect((f.queries.getQueryData(['runtime-configuration', 'host-a']) as RuntimeConfiguration).compact_percent).toBe(raw); +}); + +it('ignores a provider-only legacy override until an explicit Automatic reset', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_model: '', compact_provider: 'inference', compact_percent: 0 }); + f.render('execution'); + expect(await screen.findByText('Automatic · conversation model and provider')).toBeDefined(); + fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + await chooseCompactionMode('Summary model mode', 'Custom'); + await chooseCompactionMode('Summary model mode', 'Automatic'); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); +}); diff --git a/packages/app/test/sidebar-state.test.ts b/packages/app/test/sidebar-state.test.ts index 21cca6fb2..c0456f124 100644 --- a/packages/app/test/sidebar-state.test.ts +++ b/packages/app/test/sidebar-state.test.ts @@ -1,7 +1,38 @@ import { describe, expect, it } from 'vitest'; -import { emptySidebarState, newSessionSearch, readSidebarState, setDirectoryCollapsed, sidebarMaxWidth, sidebarRows, sidebarWidth } from '../src/sidebar-state'; +import { emptySidebarState, newSessionSearch, readSidebarState, setDirectoryCollapsed, sidebarMaxWidth, sidebarRows, sidebarWidth, mixedSidebarRows, sidebarRowKey } from '../src/sidebar-state'; const session = (id: string, cwd: string, pinned = false) => ({ id, cwd, pinned, title: id, kind: 'root', model: '', provider: '', updated_at: '', truncated: false }); +describe('mixed directory projection', () => { + const updated = (id: string, cwd: string, date: string, pinned = false) => ({ ...session(id, cwd, pinned), updated_at: date }); + it('orders by the newest loaded update, without letting pins reorder directories or session rows', () => { + const hosts = [ + { runtimeId: 'local', items: [updated('pin', '/older', '2026-01-01', true), updated('new', '/repo', '2026-03-01'), updated('old', '/repo', '2026-01-01')] }, + { runtimeId: 'remote', items: [updated('r', '/repo', '2026-02-01')] }, + ]; + const rows = mixedSidebarRows(hosts); + expect(rows.filter(row => row.kind === 'directory').map(row => [row.runtimeId, row.cwd])).toEqual([['local', '/repo'], ['remote', '/repo'], ['local', '/older']]); + expect(rows.filter(row => row.kind === 'session').map(row => row.session.id)).toEqual(['new', 'old', 'r', 'pin']); + expect(mixedSidebarRows([...hosts].reverse())).toEqual(rows); + }); + it('scopes collisions, collapse and expansion to exact runtime/path tuples', () => { + const items = Array.from({ length: 15 }, (_, index) => updated(String(index), '/repo', '2026-01-01', index === 0)); + const rows = mixedSidebarRows([{ runtimeId: 'a', items, collapsed: ['/repo'] }, { runtimeId: 'b', items, limits: new Map([['/repo', 14]]) }]); + expect(rows.filter(row => row.kind === 'session')).toHaveLength(14); + expect(rows.filter(row => row.kind === 'directory')).toHaveLength(2); + expect(new Set(rows.map(row => row.key)).size).toBe(rows.length); + expect(sidebarRowKey('directory', 'a:b', 'c')).not.toBe(sidebarRowKey('directory', 'a', 'b:c')); + expect(rows.find(row => row.kind === 'more')).toMatchObject({ runtimeId: 'b', visibleCount: 14, expanded: false }); + }); + it('breaks ties deterministically, leaves invalid timestamps last and retains path disambiguation', () => { + const hosts = [{ runtimeId: 'z', items: [updated('1', '', 'bad'), updated('2', '/repo/main', '2026-01-01'), updated('3', '/worktrees/main', '')] }, + { runtimeId: 'a', items: [updated('1', '/repo/main', '2026-01-01')] }]; + const rows = mixedSidebarRows(hosts).filter(row => row.kind === 'directory'); + expect(rows.slice(0, 2).map(row => row.runtimeId)).toEqual(['a', 'z']); + expect(rows.map(row => row.label)).toEqual(['main', 'main · repo', 'Other sessions', 'main · worktrees']); + expect(mixedSidebarRows(hosts)).toEqual(mixedSidebarRows([...hosts].reverse())); + }); +}); + describe('directory navigation projection', () => { it('groups exact directories in catalog order without merging worktrees or resolving paths', () => { const items = [session('pinned', '/repo/main', true), session('recent', '/worktrees/main'), session('older', '/repo/main'), session('unknown', ''), session('relative', './repo/main')]; diff --git a/packages/app/test/timeline-reading.test.tsx b/packages/app/test/timeline-reading.test.tsx index dcddb1ecd..7ae7e9cff 100644 --- a/packages/app/test/timeline-reading.test.tsx +++ b/packages/app/test/timeline-reading.test.tsx @@ -5,6 +5,7 @@ import { fireEvent, render, screen, + within, } from '@testing-library/react'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; import { UIProvider } from '@whip/ui'; @@ -783,3 +784,108 @@ it.each(['ctrl-wheel', 'prevented-wheel', 'pinch', 'prevented-touch'] as const)( expect(screen.queryByRole('button', { name: 'Latest' })).toBeNull(); }, ); + +function responseFixture(overrides: Partial<React.ComponentProps<typeof Timeline>> = {}) { + const f = fixture(); + const action = vi.fn(); + const answer = '**First paragraph.**\n\nSecond paragraph with *emphasis*.'; + const visible: TimelineRow[] = [ + { id: 'prompt', seq: 1, role: 'user', text: 'Start' }, + { id: 'answer', seq: 2, role: 'assistant', text: answer, sentAt: '2026-09-27T20:00:00Z' }, + { id: 'next', seq: 3, role: 'user', text: 'Next' }, + ]; + const app = (props = overrides) => <RuntimeContext.Provider value={f.runtime}><UIProvider> + <Timeline rows={visible} hasMore={false} loadOlder={f.loadOlder} readBody={() => {}} historyThroughSeq={3} responseHistoryAction={action} {...props} /> + </UIProvider></RuntimeContext.Provider>; + return { ...f, action, answer, visible, app }; +} + +it('renders one menu/copy/time footer after the final Markdown block with a shared hover owner', async () => { + const f = responseFixture(); + const mounted = render(f.app()); + const footer = mounted.container.querySelector<HTMLElement>('[data-response-actions]')!; + expect(mounted.container.querySelectorAll('[data-response-actions]')).toHaveLength(1); + expect(Array.from(footer.querySelectorAll('button, time'), item => + item.tagName === 'TIME' ? 'time' : item.getAttribute('aria-label'), + )).toEqual(['Response history actions', 'Copy response', 'time']); + expect(mounted.container.querySelectorAll('[data-message-role="assistant"]')).toHaveLength(2); + expect(footer.closest('[data-response-end]')?.textContent).toContain('Second paragraph'); + expect(footer.closest('[data-response-end]')?.textContent).not.toContain('First paragraph'); + expect(footer.querySelector('time')?.getAttribute('datetime')).toBe('2026-09-27T20:00:00Z'); + expect(footer.querySelector('time')?.getAttribute('aria-label')).toBe(new Date('2026-09-27T20:00:00Z').toLocaleString()); + await act(async () => fireEvent.click(within(footer).getByRole('button', { name: 'Copy response' }))); + expect(f.runtime.platform.copy).toHaveBeenCalledWith(f.answer); + expect(within(footer).getByRole('button', { name: 'Copied' })).toBeTruthy(); + const trigger = within(footer).getByRole('button', { name: 'Response history actions' }); + act(() => trigger.focus()); + fireEvent.keyDown(trigger, { key: 'ArrowDown' }); + await act(async () => vi.advanceTimersByTime(100)); + expect(screen.getByRole('menuitem', { name: 'Fork from here' })).toBeTruthy(); + expect(trigger.getAttribute('aria-expanded')).toBe('true'); + fireEvent.keyDown(screen.getByRole('menu'), { key: 'Escape' }); + await act(async () => vi.advanceTimersByTime(100)); + expect(trigger.getAttribute('aria-expanded')).toBe('false'); + expect(document.activeElement).toBe(trigger); + fireEvent.click(trigger); + fireEvent.click(screen.getByRole('menuitem', { name: 'Fork from here' })); + expect(f.action).toHaveBeenCalledWith(2, 'fork'); + fireEvent.click(trigger); + fireEvent.click(screen.getByRole('menuitem', { name: 'Rewind to here…' })); + expect(f.action).toHaveBeenCalledWith(2, 'rewind'); +}); + +it('shows clipboard failures only beside the response and permits retry', async () => { + const f = responseFixture(); + vi.mocked(f.runtime.platform.copy).mockRejectedValueOnce(new Error('Clipboard denied')).mockResolvedValueOnce(undefined); + const mounted = render(f.app()); + await act(async () => fireEvent.click(screen.getByRole('button', { name: 'Copy response' }))); + const footer = mounted.container.querySelector('[data-response-actions]')!; + expect(footer.querySelector('[data-error-type="action"]')?.textContent).toContain('Clipboard denied'); + expect(f.report).not.toHaveBeenCalled(); + await act(async () => fireEvent.click(screen.getByRole('button', { name: 'Could not copy. Try again.' }))); + expect(footer.querySelector('[data-error-type="action"]')).toBeNull(); +}); + +it('keeps one footer after expanded activity details and disables active/latest rewind', () => { + const f = responseFixture(); + const activity = { id: 'activity', seq: 3, role: 'activity', text: '', cells: [], memberIds: ['thought'], memberSeqs: [3, 4], + items: [{ id: 'thought', kind: 'reasoning' as const, row: { id: 'thought', seq: 3, role: 'reasoning', text: 'Reasoning, not copied.' } }] }; + const visible = [...f.visible.slice(0, -1), activity]; + const mounted = render(f.app({ rows: visible, historyThroughSeq: 4 })); + fireEvent.click(screen.getByRole('button', { name: 'Thought' })); + expect(mounted.container.querySelectorAll('[data-response-actions]')).toHaveLength(1); + fireEvent.click(screen.getAllByRole('button', { name: /Thought/ }).at(-1)!); + expect(mounted.container.querySelector('[data-response-actions]')?.closest('[data-response-end]')?.textContent).toContain('Reasoning'); + fireEvent.click(screen.getByRole('button', { name: 'Response history actions' })); + expect(screen.getByRole('menuitem', { name: 'Rewind to here…' }).getAttribute('aria-disabled')).toBe('true'); + fireEvent.click(screen.getByRole('menuitem', { name: 'Fork from here' })); + expect(f.action).toHaveBeenCalledWith(4, 'fork'); + mounted.rerender(f.app({ active: true, rewindDisabled: true })); + fireEvent.click(screen.getByRole('button', { name: 'Response history actions' })); + expect(screen.getByRole('menuitem', { name: 'Rewind to here…' }).getAttribute('aria-disabled')).toBe('true'); +}); + +it('omits dead menus offline, in child transcripts, and for uncertain boundaries, but keeps copy/date', () => { + const f = responseFixture(); + const mounted = render(f.app({ connected: false })); + for (const props of [{ connected: false }, { responseHistoryAction: undefined }, { hasMore: true, rows: f.visible.slice(1) }, { historyReady: false }]) { + mounted.rerender(f.app(props)); + expect(screen.queryByRole('button', { name: 'Response history actions' })).toBeNull(); + expect(screen.getByRole('button', { name: /Copy (visible )?response/ })).toBeTruthy(); + } + mounted.rerender(f.app({ rows: [f.visible[1]!], historyThroughSeq: undefined })); + expect(screen.queryByRole('button', { name: 'Response history actions' })).toBeNull(); +}); + +it('allows image-only response date/history with no empty copy and omits invalid old times', () => { + const f = responseFixture(); + const image = { ...f.visible[1]!, text: '', images: [{ url: 'data:image/png;base64,AAAA' }] }; + const mounted = render(f.app({ rows: [image], historyThroughSeq: 2 })); + expect(screen.queryByRole('button', { name: 'Copy response' })).toBeNull(); + expect(screen.getByRole('button', { name: 'Response history actions' })).toBeTruthy(); + expect(mounted.container.querySelector('[data-response-actions] time')).toBeTruthy(); + mounted.rerender(f.app({ rows: [{ ...f.visible[1]!, sentAt: 'invalid' }], historyThroughSeq: 2 })); + expect(mounted.container.querySelector('[data-response-actions] time')).toBeNull(); + mounted.rerender(f.app({ rows: [{ ...f.visible[1]!, live: true }], active: true })); + expect(mounted.container.querySelector('[data-response-actions]')).toBeNull(); +}); diff --git a/packages/app/test/trace-view.test.tsx b/packages/app/test/trace-view.test.tsx index ba2f6c058..541d0ce4a 100644 --- a/packages/app/test/trace-view.test.tsx +++ b/packages/app/test/trace-view.test.tsx @@ -206,6 +206,23 @@ it('names a fold "compaction" and offers the interned prompt and summary for rea expect(screen.queryByText(/recorded no excerpt/)).toBeNull(); }); +it.each([ + ['openai', 'Custom summarizer unavailable; using this conversation’s model.'], + ['openai', ''], + ['', ''], +])('shows the recorded compaction route and fallback without consulting saved defaults (%s, %s)', async (provider, fallback) => { + const compact = span({ id: 'compact-route', parentId: 'turn', kind: 'llm', name: 'Context summary', + attrs: { purpose: 'compaction', model: 'conversation-model', provider, compaction_fallback: fallback } }); + const f = fixture({ spans: { turn: spans[0]!, [compact.id]: compact } }); + render(f.app()); + fireEvent.click(await screen.findByRole('treeitem', { name: /Context summary/ })); + const details = screen.getByRole('complementary', { name: 'Span details' }); + expect(details.textContent).toContain('Summary route'); + expect(details.textContent).toContain('conversation-model · ' + (provider || 'Provider not recorded')); + if (fallback) expect(details.textContent).toContain(fallback); + else expect(details.textContent).not.toContain('Custom summarizer unavailable'); +}); + it('explains loading, disconnected, truncated and failed evidence without inventing spans', async () => { const f = fixture({ loaded: false, loading: true, spans: {} }); const mounted = render(f.app()); diff --git a/packages/ui/README.md b/packages/ui/README.md index 9ce4c41c4..e9e62006f 100644 --- a/packages/ui/README.md +++ b/packages/ui/README.md @@ -89,6 +89,9 @@ Buttons accept `variant=primary|secondary|ghost|danger`, `size=sm|md|lg`, `CopyButton` accepts `showLabel` to display its label beside the icon, including copy success or failure feedback. The default remains an icon button. +Popover accepts optional Base UI `side` and `align` placement, with collision handling +kept in the shared positioner. Its title has no browser-default heading margins. + Tooltip accepts `label`, a trigger child, optional `delay`, `disableHoverablePopup`, `xstyle`, and Base UI `side`, `align`, `sideOffset`, `collisionPadding`, and `collisionAvoidance` placement options. Rich tooltip content @@ -322,9 +325,14 @@ separate acceptance work. Dialog accepts an optional `header` slot for controls such as a search input; its `title` remains the accessible dialog name. `initialFocus` and `finalFocus` -forward Base UI focus destinations. Default titled dialogs are unchanged. +forward Base UI focus destinations. `headerXstyle` and `bodyXstyle` let composed dialogs adjust section spacing and flex sizing while retaining the shared title, close control and focus behavior. +Dialog and AlertDialog size naturally to their content; a fixed Base UI viewport +scrolls the entire popup over the backdrop, not its body. Short dialogs remain +centered; tall dialogs start at the former capped-height offset, with at least +16px of outer space. Sheet retains its edge-anchored, viewport-height scrolling +surface. Explicit consumer height/overflow styles still support bounded pickers. Text inputs, textareas, combobox inputs, and number inputs indicate focus by changing their one-pixel border to `surface.secondaryText`. They do not add an diff --git a/packages/ui/src/overlays.tsx b/packages/ui/src/overlays.tsx index e415b5087..2866e25fb 100644 --- a/packages/ui/src/overlays.tsx +++ b/packages/ui/src/overlays.tsx @@ -17,12 +17,12 @@ import type { Option } from './forms'; export interface DialogProps extends Styled {headerXstyle?: Styled['xstyle']; bodyXstyle?: Styled['xstyle']; open: boolean; onOpenChange: (open: boolean) => void; title: ReactNode; header?: ReactNode; description?: ReactNode; children?: ReactNode; footer?: ReactNode; closeLabel?: string; initialFocus?: BaseDialog.Popup.Props['initialFocus']; finalFocus?: BaseDialog.Popup.Props['finalFocus']} export function Dialog({open, onOpenChange, title, header, description, children, footer, closeLabel = 'Close', initialFocus, finalFocus, headerXstyle, bodyXstyle, xstyle}: DialogProps) { const overlay = useNativeOverlay(open, onOpenChange); - return <BaseDialog.Root {...overlay}><BaseDialog.Portal><BaseDialog.Backdrop {...stylex.props(styles.backdrop)}/><BaseDialog.Popup initialFocus={initialFocus} finalFocus={finalFocus} {...stylex.props(styles.dialog, xstyle)}><div {...stylex.props(styles.dialogHeader, headerXstyle)}><div {...stylex.props(styles.grow)}><BaseDialog.Title {...stylex.props(styles.dialogTitle, header != null && dialogStyles.hiddenTitle)}>{title}</BaseDialog.Title>{header}{description && <BaseDialog.Description {...stylex.props(styles.dialogDescription)}>{description}</BaseDialog.Description>}</div><BaseDialog.Close render={<Button aria-label={closeLabel} variant="ghost" xstyle={styles.icon}><X size={16}/></Button>}/></div><div {...stylex.props(styles.stack, bodyXstyle)}>{children}</div>{footer && <div {...stylex.props(styles.footer)}>{footer}</div>}</BaseDialog.Popup></BaseDialog.Portal></BaseDialog.Root>; + return <BaseDialog.Root {...overlay}><BaseDialog.Portal><BaseDialog.Backdrop {...stylex.props(styles.backdrop)}/><BaseDialog.Viewport {...stylex.props(styles.dialogViewport)}><BaseDialog.Popup initialFocus={initialFocus} finalFocus={finalFocus} {...stylex.props(styles.dialog, xstyle)}><div {...stylex.props(styles.dialogHeader, headerXstyle)}><div {...stylex.props(styles.grow)}><BaseDialog.Title {...stylex.props(styles.dialogTitle, header != null && dialogStyles.hiddenTitle)}>{title}</BaseDialog.Title>{header}{description && <BaseDialog.Description {...stylex.props(styles.dialogDescription)}>{description}</BaseDialog.Description>}</div><BaseDialog.Close render={<Button aria-label={closeLabel} variant="ghost" xstyle={styles.icon}><X size={16}/></Button>}/></div><div {...stylex.props(styles.stack, bodyXstyle)}>{children}</div>{footer && <div {...stylex.props(styles.footer)}>{footer}</div>}</BaseDialog.Popup></BaseDialog.Viewport></BaseDialog.Portal></BaseDialog.Root>; } export function Sheet({xstyle, ...props}: DialogProps) {return <Dialog {...props} xstyle={[styles.sheet, xstyle]}/>;} export function AlertDialog({open, onOpenChange, title, description, children, confirmLabel = 'Continue', onConfirm, loading, danger = false, finalFocus, xstyle}: Omit<DialogProps, 'footer' | 'closeLabel' | 'initialFocus'> & {confirmLabel?: string; onConfirm: () => void; loading?: boolean; danger?: boolean}) { const overlay = useNativeOverlay(open, onOpenChange); - return <BaseAlertDialog.Root {...overlay}><BaseAlertDialog.Portal><BaseAlertDialog.Backdrop {...stylex.props(styles.backdrop)}/><BaseAlertDialog.Popup finalFocus={finalFocus} {...stylex.props(styles.dialog, xstyle)}><BaseAlertDialog.Title {...stylex.props(styles.dialogTitle)}>{title}</BaseAlertDialog.Title>{description && <BaseAlertDialog.Description {...stylex.props(styles.dialogDescription)}>{description}</BaseAlertDialog.Description>}{children}<div {...stylex.props(styles.footer)}><BaseAlertDialog.Close render={<Button disabled={loading}>Cancel</Button>}/><Button variant={danger ? 'danger' : 'primary'} loading={loading} onClick={onConfirm}>{confirmLabel}</Button></div></BaseAlertDialog.Popup></BaseAlertDialog.Portal></BaseAlertDialog.Root>; + return <BaseAlertDialog.Root {...overlay}><BaseAlertDialog.Portal><BaseAlertDialog.Backdrop {...stylex.props(styles.backdrop)}/><BaseAlertDialog.Viewport {...stylex.props(styles.dialogViewport)}><BaseAlertDialog.Popup finalFocus={finalFocus} {...stylex.props(styles.dialog, xstyle)}><BaseAlertDialog.Title {...stylex.props(styles.dialogTitle)}>{title}</BaseAlertDialog.Title>{description && <BaseAlertDialog.Description {...stylex.props(styles.dialogDescription)}>{description}</BaseAlertDialog.Description>}{children}<div {...stylex.props(styles.footer)}><BaseAlertDialog.Close render={<Button disabled={loading}>Cancel</Button>}/><Button variant={danger ? 'danger' : 'primary'} loading={loading} onClick={onConfirm}>{confirmLabel}</Button></div></BaseAlertDialog.Popup></BaseAlertDialog.Viewport></BaseAlertDialog.Portal></BaseAlertDialog.Root>; } export interface MenuItem {id: string; label: ReactNode; onSelect?: () => void; disabled?: boolean; danger?: boolean; shortcut?: string; icon?: ReactNode; separator?: boolean; items?: readonly MenuItem[]} function SubMenu({item, content}: {item: MenuItem; content: ReactNode}) { @@ -48,9 +48,9 @@ export function ContextMenu({children, items, onOpenChange}: {children: ReactEle const overlay = useNativeOverlay(undefined, onOpenChange); return <BaseContextMenu.Root {...overlay}><BaseContextMenu.Trigger render={children}/><BaseContextMenu.Portal><BaseContextMenu.Positioner {...stylex.props(styles.positioner)}><BaseContextMenu.Popup {...stylex.props(styles.popup)}><MenuItems items={items}/></BaseContextMenu.Popup></BaseContextMenu.Positioner></BaseContextMenu.Portal></BaseContextMenu.Root>; } -export function Popover({trigger, title, children, open, onOpenChange, xstyle}: {trigger: ReactElement; title?: ReactNode; children: ReactNode; open?: boolean; onOpenChange?: (value: boolean) => void} & Styled) { +export function Popover({trigger, title, children, open, onOpenChange, side, align, xstyle}: {trigger: ReactElement; title?: ReactNode; children: ReactNode; open?: boolean; onOpenChange?: (value: boolean) => void; side?: BasePopover.Positioner.Props['side']; align?: BasePopover.Positioner.Props['align']} & Styled) { const overlay = useNativeOverlay(open, onOpenChange); - return <BasePopover.Root {...overlay}><BasePopover.Trigger render={trigger}/><BasePopover.Portal><BasePopover.Positioner sideOffset={8} {...stylex.props(styles.positioner)}><BasePopover.Popup {...stylex.props(styles.popup, xstyle)}>{title && <BasePopover.Title {...stylex.props(styles.label)}>{title}</BasePopover.Title>}{children}</BasePopover.Popup></BasePopover.Positioner></BasePopover.Portal></BasePopover.Root>; + return <BasePopover.Root {...overlay}><BasePopover.Trigger render={trigger}/><BasePopover.Portal><BasePopover.Positioner side={side} align={align} sideOffset={8} {...stylex.props(styles.positioner)}><BasePopover.Popup {...stylex.props(styles.popup, xstyle)}>{title && <BasePopover.Title {...stylex.props(styles.label, styles.popupTitle)}>{title}</BasePopover.Title>}{children}</BasePopover.Popup></BasePopover.Positioner></BasePopover.Portal></BasePopover.Root>; } export function CommandPicker({open, onOpenChange, items, onSelect}: {open: boolean; onOpenChange: (open: boolean) => void; items: readonly Option[]; onSelect: (value: string) => void}) { const input = useRef<HTMLInputElement>(null); diff --git a/packages/ui/src/styles.stylex.ts b/packages/ui/src/styles.stylex.ts index 2066cd452..43d1a9a95 100644 --- a/packages/ui/src/styles.stylex.ts +++ b/packages/ui/src/styles.stylex.ts @@ -42,6 +42,7 @@ export const styles = stylex.create({ switchThumb: {display: 'block', width: 14, height: 14, borderRadius: 10, backgroundColor: colors.background, transitionProperty: 'transform', transitionDuration: appearance.motionNormal}, switchThumbOn: {transform: 'translateX(12px)'}, popup: {backgroundColor: colors.panel, color: colors.foreground, border: `1px solid ${surface.quietBorder}`, borderRadius: 8, padding: 4, minWidth: 180, maxWidth: 'min(420px, calc(100vw - 24px))', maxHeight: 'min(var(--available-height), 360px)', overflow: 'auto', boxShadow: '0 8px 28px rgb(0 0 0 / 0.12)', fontSize: typography.size13, outline: 'none'}, + popupTitle: {margin: 0}, positioner: {zIndex: 100}, item: {display: 'flex', alignItems: 'center', gap: 8, paddingBlock: {default: 7, [scale.touch]: 12}, paddingInline: 8, borderRadius: 4, cursor: 'default', outline: 'none', minHeight: 30}, highlighted: {backgroundColor: colors.hover}, @@ -50,14 +51,17 @@ export const styles = stylex.create({ selectValue: {minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis'}, chevron: {marginInlineStart: 'auto', color: surface.secondaryText, flexShrink: 0}, backdrop: {position: 'fixed', inset: 0, backgroundColor: surface.overlay, zIndex: 80}, - dialog: {fontFamily: typography.sans, fontSize: typography.size13, lineHeight: '1.5385', position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: 'min(520px, calc(100vw - 32px))', maxHeight: 'min(85dvh, 860px)', backgroundColor: colors.background, color: colors.foreground, border: `1px solid ${surface.quietBorder}`, borderRadius: scale.radiusDialog, padding: 24, display: 'flex', flexDirection: 'column', gap: 20, zIndex: 81, overflow: 'auto', boxShadow: '0 16px 64px rgb(0 0 0 / 0.16)'}, - sheet: {top: 0, right: 0, bottom: 0, left: 'auto', transform: 'none', width: 'min(440px, 100vw)', maxHeight: '100dvh', borderRadius: 0, padding: 20}, + // Keep the old capped dialog's top offset, but let its entire surface scroll. + dialogViewport: {position: 'fixed', inset: 0, zIndex: 81, display: 'flex', flexDirection: 'column', alignItems: 'center', paddingBlock: 'max(16px, calc((100dvh - min(85dvh, 860px)) / 2))', overflowY: 'auto', overscrollBehaviorY: 'contain'}, + dialog: {fontFamily: typography.sans, fontSize: typography.size13, lineHeight: '1.5385', position: 'relative', marginBlock: 'auto', flexShrink: 0, width: 'min(520px, calc(100vw - 32px))', backgroundColor: colors.background, color: colors.foreground, border: `1px solid ${surface.quietBorder}`, borderRadius: scale.radiusDialog, padding: 24, display: 'flex', flexDirection: 'column', gap: 20, zIndex: 81, boxShadow: '0 16px 64px rgb(0 0 0 / 0.16)'}, + sheet: {position: 'fixed', top: 0, right: 0, bottom: 0, left: 'auto', marginBlock: 0, width: 'min(440px, 100vw)', maxHeight: '100dvh', overflow: 'auto', borderRadius: 0, padding: 20}, dialogHeader: {display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16}, dialogTitle: {fontSize: typography.size17, fontWeight: 600, lineHeight: '1.4118', letterSpacing: '-0.015em', margin: 0}, dialogDescription: {fontSize: typography.size13, lineHeight: '1.5385', color: surface.secondaryText, marginTop: 6, marginBottom: 0}, footer: {display: 'flex', gap: 8, justifyContent: 'flex-end', flexWrap: 'wrap'}, separator: {height: 1, minHeight: 1, border: 0, marginBlock: 8, backgroundColor: surface.quietBorder}, - tooltip: {fontSize: typography.size12, lineHeight: '1.5', borderRadius: 5, paddingBlock: 5, paddingInline: 8, maxWidth: 300, backgroundColor: colors.foreground, color: colors.background}, + // Size to content; only cap near the viewport so long labels wrap instead of clipping short. + tooltip: {fontSize: typography.size12, lineHeight: '1.5', borderRadius: 5, paddingBlock: 5, paddingInline: 8, width: 'max-content', maxWidth: 'min(420px, calc(100vw - 24px))', backgroundColor: colors.foreground, color: colors.background}, tabList: {display: 'flex', gap: 4, borderBottom: `1px solid ${surface.quietBorder}`, overflowX: 'auto', paddingBottom: 4}, tab: {backgroundColor: 'transparent', borderColor: 'transparent', color: surface.secondaryText}, tabActive: {backgroundColor: colors.hover, color: colors.foreground}, diff --git a/packages/ui/stories/Activity.stories.tsx b/packages/ui/stories/Activity.stories.tsx index a158d3b5a..bd3837686 100644 --- a/packages/ui/stories/Activity.stories.tsx +++ b/packages/ui/stories/Activity.stories.tsx @@ -1,16 +1,13 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import * as stylex from '@stylexjs/stylex'; -import { ActivityIndicator, Button, Stack, useTheme } from '../src'; +import { ActivityIndicator, Stack } from '../src'; const styles = stylex.create({ row: { flexDirection: 'row', alignItems: 'center' } }); function Example() { - const { display, setDisplay } = useTheme(); return <Stack> - <Stack xstyle={styles.row}><ActivityIndicator active reduceMotion={display.motion === 'reduce'} /><span>Reading files</span></Stack> - <Button variant="ghost" onClick={() => setDisplay({ motion: display.motion === 'reduce' ? 'system' : 'reduce' })}> - {display.motion === 'reduce' ? 'Use system motion' : 'Pause activity animation'} - </Button> + <Stack xstyle={styles.row}><ActivityIndicator active /><span>Reading files</span></Stack> + <Stack xstyle={styles.row}><ActivityIndicator active reduceMotion /><span>Reduced motion</span></Stack> <Stack xstyle={styles.row}><ActivityIndicator active={false} /><span>Updates paused</span></Stack> </Stack>; } diff --git a/packages/ui/stories/Library.stories.tsx b/packages/ui/stories/Library.stories.tsx index 3767efcfb..b2ad027e8 100644 --- a/packages/ui/stories/Library.stories.tsx +++ b/packages/ui/stories/Library.stories.tsx @@ -5,7 +5,7 @@ import { MoreHorizontal, Plus, Activity } from 'lucide-react'; import { expect, userEvent, within, waitFor } from 'storybook/test'; import { Accordion, CodeBlock, Alert, AlertDialog, Avatar, Badge, Breadcrumbs, Button, ButtonGroup, Checkbox, Collapsible, Combobox, CommandPicker, ContextMenu, CopyButton, Dialog, EmptyState, ErrorState, Field, Fieldset, IconButton, Input, Kbd, Label, Link, Menu, Meter, NumberField, Panel, Popover, Progress, RadioGroup, Row, ScrollArea, Select, Separator, SettingsRow, Sheet, Skeleton, Spinner, Stack, StatusIndicator, Switch, Tabs, Textarea, ThemePicker, ThemePreview, ToggleGroup, Tooltip, useToast, useTheme, themeCatalog, VisuallyHidden } from '../src'; -const storyStyles = stylex.create({narrow: {maxWidth: 390}, width: (value: number) => ({width: value})}); +const storyStyles = stylex.create({narrow: {maxWidth: 390}, width: (value: number) => ({width: value}), scrollPage: {minHeight: 2000}, boundedDialog: {height: 'min(560px, calc(100dvh - 48px))', overflow: 'hidden'}, boundedBody: {flex: 1, minHeight: 0, overflowY: 'auto'}}); const options = [{value: 'balanced', label: 'Balanced', description: 'Steady progress within a bounded budget'}, {value: 'fast', label: 'Fast'}, {value: 'thorough', label: 'Thorough'}, {value: 'unavailable', label: 'Unavailable on this host', disabled: true}]; function Actions() { const toast = useToast(); @@ -20,6 +20,21 @@ function Overlays() { const items = [{id: 'rename', label: 'Rename session', onSelect: () => setDialog(true)}, {id: 'delete', label: 'Delete session', danger: true, onSelect: () => setAlert(true)}]; return <Stack><Row><Button onClick={() => setDialog(true)}>Open dialog</Button><Button onClick={() => setSheet(true)}>Open sheet</Button><Button onClick={() => setCommands(true)}>Find command</Button><Menu trigger={<IconButton label="Session menu"><MoreHorizontal size={16}/></IconButton>} items={items}/><Popover title="Agent status" trigger={<Button>Popover</Button>}><p>The child agent is waiting for input.</p></Popover></Row><ContextMenu items={items}><Panel>Right-click this session summary.</Panel></ContextMenu><Dialog open={dialog} onOpenChange={setDialog} title="Session settings" description="Updates are shared with other clients." footer={<Button onClick={() => setDialog(false)}>Save changes</Button>}><Field label="Name"><Input defaultValue="Inspect queue lifecycle"/></Field><Menu trigger={<Button>More actions</Button>} items={items}/><Button onClick={() => setAlert(true)}>Open nested confirmation</Button><ThemePicker/></Dialog><Sheet open={sheet} onOpenChange={setSheet} title="Agent details"><p>Read-only activity and context live here.</p></Sheet><AlertDialog open={alert} onOpenChange={setAlert} title="Delete this session?" description="This removes its conversation history." confirmLabel="Delete session" danger onConfirm={() => setAlert(false)}/><CommandPicker open={commands} onOpenChange={setCommands} items={options} onSelect={() => {}}/></Stack>; } +function DialogScrollingExample() { + const [kind, setKind] = useState<'short' | 'tall' | 'bounded' | 'sheet' | null>(null); + const [confirm, setConfirm] = useState(false); + const Popup = kind === 'sheet' ? Sheet : Dialog; + return <div {...stylex.props(storyStyles.scrollPage)}> + <Row>{(['short', 'tall', 'bounded', 'sheet'] as const).map(value => <Button key={value} onClick={() => setKind(value)}>Open {value} example</Button>)}</Row> + <Popup open={kind !== null} onOpenChange={open => {if (!open) setKind(null);}} title="Scrolling example" + xstyle={kind === 'bounded' && storyStyles.boundedDialog} bodyXstyle={kind === 'bounded' && storyStyles.boundedBody} + footer={<Button onClick={() => setKind(null)}>Finish example</Button>}> + <Button onClick={() => setConfirm(true)}>Open confirmation</Button> + {Array.from({length: kind === 'short' ? 1 : 40}, (_, index) => <p key={index}>Section {index + 1}. The whole dialog surface should move together over the background, without an inner scrollbar.</p>)} + <AlertDialog open={confirm} onOpenChange={setConfirm} title="Nested confirmation" onConfirm={() => setConfirm(false)}/> + </Popup> + </div>; +} function Content() { const [tab, setTab] = useState('conversation'); return <Stack><Breadcrumbs><Link href="#">Session</Link><span aria-hidden>/</span><span>Explore</span></Breadcrumbs><Row><Avatar name="Explore agent"/><StatusIndicator tone="success">Completed</StatusIndicator><Badge tone="warning">Waiting for input</Badge><Badge tone="error">Interrupted</Badge><Badge tone="info">Reconnecting</Badge><Spinner/><VisuallyHidden>Loading the latest state</VisuallyHidden></Row><Progress label="Context use" value={42}/><Meter label="Budget consumed" value={18} max={100}/><Tabs value={tab} onValueChange={setTab} items={[{value: 'conversation', label: 'Conversation', content: <p>Your agent has finished the focused check.</p>}, {value: 'activity', label: 'Activity', content: <p>Three child agents are still working.</p>}]}/><Collapsible title="Read tool output"><pre>Stable, bounded tool output.</pre></Collapsible><Accordion items={[{id: 'reasoning', title: 'Reasoning', content: 'Inspect assumptions before making changes.'}]}/><Alert title="Reconnecting" tone="info">Your accepted work continues on the host.</Alert><Skeleton/><SettingsRow label="Show reasoning" description="Keep longer explanations collapsed."><Switch aria-label="Show reasoning"/></SettingsRow><Separator/><ScrollArea aria-label="Long output"><p>Scroll regions retain native keyboard and touch behavior.</p></ScrollArea><EmptyState title="Your work stays on the host" description="Choose a conversation or begin a new one." icon={<Activity size={24}/>} action={<Button>New session</Button>}/><ErrorState error={new Error('The host is temporarily unavailable.')} action={<Button>Try again</Button>}/></Stack>; @@ -30,6 +45,7 @@ type Story = StoryObj<typeof meta>; export const ActionStates: Story = {render: () => <Actions/>}; export const FormStates: Story = {render: () => <Controls/>}; export const OverlayStates: Story = {render: () => <Overlays/>, play: async ({canvasElement}) => {const canvas = within(canvasElement); await userEvent.click(canvas.getByRole('button', {name: 'Open dialog'})); const body = within(canvasElement.ownerDocument.body); await expect(body.getByRole('dialog')).toBeVisible(); await waitFor(() => expect(body.getByRole('dialog').contains(canvasElement.ownerDocument.activeElement)).toBe(true)); await userEvent.keyboard('{Escape}'); await waitFor(() => expect(canvas.getByRole('button', {name: 'Open dialog'})).toHaveFocus()); canvasElement.dataset.playComplete = 'true';}}; +export const DialogScrolling: Story = {render: () => <DialogScrollingExample/>}; export const ContentStates: Story = {render: () => <Content/>}; export const Appearance: Story = {render: () => <Stack><ThemePicker/><ThemePreview/><Actions/><Controls/></Stack>}; export const NarrowLayout: Story = {render: () => <div {...stylex.props(storyStyles.narrow)}><Stack><Actions/><Controls/><Content/></Stack></div>}; diff --git a/packages/ui/tests/browser.mjs b/packages/ui/tests/browser.mjs index 8e0f566f6..239831001 100644 --- a/packages/ui/tests/browser.mjs +++ b/packages/ui/tests/browser.mjs @@ -98,6 +98,105 @@ try { await page.keyboard.press('Escape'); await page.getByRole('dialog').waitFor({state: 'hidden'}); report.checks.push('nested dialogs and focus dismissal'); + // Default popups scroll as one surface; bounded pickers and sheets opt into inner scrolling. + for (const {width, height, theme} of [ + {width: 1080, height: 960, theme: 'light'}, + {width: 1440, height: 1200, theme: 'dark'}, + {width: 390, height: 640, theme: 'light'}, + {width: 390, height: 640, theme: 'dark'}, + ]) { + await page.setViewportSize({width, height}); + await page.goto(story('dialog-scrolling', theme)); + await page.evaluate(() => document.fonts.ready); + const popup = page.getByRole('dialog', {name: 'Scrolling example', exact: true}); + const viewport = popup.locator('..'); + await page.getByRole('button', {name: 'Open short example'}).click(); + const short = await popup.boundingBox(); + expect(Math.abs(short.y - (height - short.height) / 2)).toBeLessThan(2); + await page.keyboard.press('Escape'); + await expect(page.getByRole('button', {name: 'Open short example'})).toBeFocused(); + + const trigger = page.getByRole('button', {name: 'Open tall example'}); + await trigger.click(); + const tall = await popup.boundingBox(); + const offset = Math.max(16, (height - Math.min(height * 0.85, 860)) / 2); + expect(Math.abs(tall.y - offset)).toBeLessThan(2); + expect(tall.height).toBeGreaterThan(height); + expect(await popup.evaluate(node => getComputedStyle(node).overflowY)).toBe('visible'); + expect(await viewport.evaluate(node => node.scrollTop)).toBe(0); + const documentScroll = await page.evaluate(() => window.scrollY); + await page.screenshot({path: resolve(results, 'dialog-' + theme + '-' + width + '-top.png')}); + + // Nested confirmation sits above the parent and keeps its dismissal/focus contract. + await popup.getByRole('button', {name: 'Open confirmation'}).click(); + const confirmation = page.getByRole('alertdialog'); + const confirmationBox = await confirmation.boundingBox(); + expect(Math.abs(confirmationBox.y - (height - confirmationBox.height) / 2)).toBeLessThan(2); + await page.mouse.click(4, 4); + await expect(confirmation).toBeVisible(); + await confirmation.getByRole('button', {name: 'Cancel', exact: true}).click(); + await expect(popup.getByRole('button', {name: 'Open confirmation'})).toBeFocused(); + + // Wheel over the popup and then the empty backdrop area must move the same viewport. + await page.mouse.move(width / 2, height / 2); + await page.mouse.wheel(0, 240); + await expect.poll(() => viewport.evaluate(node => node.scrollTop)).toBeGreaterThan(0); + const firstScroll = await viewport.evaluate(node => node.scrollTop); + await page.mouse.move(4, height / 2); + await page.mouse.wheel(0, 240); + await expect.poll(() => viewport.evaluate(node => node.scrollTop)).toBeGreaterThan(firstScroll); + const scrolled = await popup.boundingBox(); + const scrollTop = await viewport.evaluate(node => node.scrollTop); + expect(Math.abs(scrolled.height - tall.height)).toBeLessThan(1); + expect(Math.abs(scrolled.y - (tall.y - scrollTop))).toBeLessThan(2); + expect(await popup.evaluate(node => node.scrollTop)).toBe(0); + expect(await page.evaluate(() => window.scrollY)).toBe(documentScroll); + + await viewport.evaluate(node => {node.scrollTop = node.scrollHeight;}); + const bottom = await popup.boundingBox(); + expect(Math.abs(height - bottom.y - bottom.height - offset)).toBeLessThan(2); + await expect(popup.getByRole('button', {name: 'Finish example'})).toBeInViewport(); + await page.screenshot({path: resolve(results, 'dialog-' + theme + '-' + width + '-bottom.png')}); + await page.mouse.wheel(0, 400); + expect(await page.evaluate(() => window.scrollY)).toBe(documentScroll); + await page.keyboard.press('Escape'); + await expect(trigger).toBeFocused(); + + await trigger.click(); + expect(await viewport.evaluate(node => node.scrollTop)).toBe(0); + // Native focus navigation must bring the footer into view without a custom scroll handler. + await popup.getByRole('button', {name: 'Close', exact: true}).focus(); + await page.keyboard.press('Shift+Tab'); + await expect(popup.getByRole('button', {name: 'Finish example'})).toBeFocused(); + await expect(popup.getByRole('button', {name: 'Finish example'})).toBeInViewport(); + await page.mouse.click(4, 4); + await expect(popup).toBeHidden(); + + await page.getByRole('button', {name: 'Open bounded example'}).click(); + const bounded = await popup.boundingBox(); + expect(Math.abs(bounded.height - Math.min(560, height - 48))).toBeLessThan(2); + const body = popup.getByRole('button', {name: 'Open confirmation'}).locator('..'); + await body.evaluate(node => {node.scrollTop = 240;}); + expect(await body.evaluate(node => node.scrollTop)).toBe(240); + expect(await viewport.evaluate(node => node.scrollTop)).toBe(0); + await page.keyboard.press('Escape'); + + await page.getByRole('button', {name: 'Open sheet example'}).click(); + const sheet = await popup.boundingBox(); + expect(sheet.y).toBe(0); + expect(sheet.height).toBe(height); + expect(sheet.x + sheet.width).toBe(width); + await popup.evaluate(node => {node.scrollTop = 240;}); + expect(await popup.evaluate(node => node.scrollTop)).toBe(240); + expect(await viewport.evaluate(node => node.scrollTop)).toBe(0); + expect((await popup.boundingBox()).y).toBe(0); + await page.keyboard.press('Escape'); + expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(width); + } + report.checks.push('dialog viewport scrolling, stable height/top offset, bottom spacing, nested focus, bounded pickers and sheets in light/dark desktop/narrow layouts'); + await page.setViewportSize({width: 1080, height: 960}); + await page.goto(story('overlay-states', 'dark')); + await page.waitForFunction(() => document.getElementById('storybook-root')?.dataset.playComplete === 'true'); const commandTrigger = page.getByRole('button', {name: 'Find command', exact: true}); const commandSearch = page.getByRole('combobox', {name: 'Search commands'}); const commandDialog = page.getByRole('dialog', {name: 'Commands', exact: true}); diff --git a/scripts/update-local.mjs b/scripts/update-local.mjs index ebc478c10..ad831e4a9 100644 --- a/scripts/update-local.mjs +++ b/scripts/update-local.mjs @@ -25,7 +25,8 @@ WHIP_DESKTOP_NOTARIZE=1 uses the existing packaging notarization settings. See README.md for details and recovery. No Git pull or release publication occurs.`; async function build(env) { - for (const [file, args] of [['npm', ['ci']], [process.execPath, ['node_modules/electron/install.js']], + // Git dependencies resolve their own build tooling; revalidate cached registry metadata. + for (const [file, args] of [['npm', ['ci', '--prefer-online']], [process.execPath, ['node_modules/electron/install.js']], [process.execPath, ['apps/desktop/scripts/package.mjs']]]) { await new Promise((resolve, reject) => { const child = spawn(file, args, { cwd: repositoryRoot, stdio: 'inherit', env }); From edf7528907dd31522dff408ce9ca3f73cdcc3efc Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Mon, 28 Sep 2026 17:27:31 -0700 Subject: [PATCH 11/67] new build skips --- .easignore | 4 +- .github/workflows/ci.yml | 8 + .github/workflows/desktop-check.yml | 4 + .github/workflows/desktop-release.yml | 4 + .github/workflows/mobile.yml | 10 + .github/workflows/publish-cli.yml | 20 + .gitignore | 4 +- CONTRIBUTING.md | 23 +- README.md | 3 +- Taskfile.yaml | 8 +- .../src/content/docs/typescript-sdk/index.mdx | 6 +- apps/mobile/README.md | 6 + apps/mobile/package.json | 2 +- .../mobile/scripts/eas-build-post-install.mjs | 47 + .../scripts/eas-build-post-install.test.mjs | 67 + apps/web/scripts/settings.mjs | 105 +- docs/README.md | 1 + docs/agent-loop.md | 2 +- docs/desktop.md | 8 +- docs/features.md | 9 +- docs/frontend.md | 45 +- docs/mobile-release.md | 26 +- docs/mobile.md | 8 +- docs/models-providers.md | 44 +- docs/protocol-v2.md | 10 +- docs/setup.md | 15 +- docs/web-app.md | 7 +- packages/app/src/compaction-settings.tsx | 100 +- packages/app/src/details/session-controls.tsx | 4 +- packages/app/src/model-selection.tsx | 36 +- packages/app/src/settings/configuration.tsx | 5 +- packages/app/src/settings/navigation.ts | 4 +- packages/app/test/inspector.test.tsx | 72 +- packages/app/test/model-selection.test.tsx | 1 + .../app/test/settings-configuration.test.tsx | 131 +- packages/protocol/README.md | 30 +- packages/protocol/generated/index.d.ts | 4526 - packages/protocol/generated/index.js | 1306 - .../protocol/generated/request-validators.js | 73085 ---------------- .../protocol/generated/response-validators.js | 66788 -------------- packages/protocol/package.json | 5 +- packages/protocol/schema/Accepted.json | 15 - .../protocol/schema/AgentCancelParams.json | 19 - .../protocol/schema/AgentInputParams.json | 168 - packages/protocol/schema/AgentListResult.json | 179 - .../protocol/schema/AgentSubmitResult.json | 28 - .../schema/AgentTranscriptResult.json | 1183 - packages/protocol/schema/ArchiveParams.json | 15 - packages/protocol/schema/ArchiveResult.json | 15 - .../schema/BoundedTranscriptPage.json | 662 - packages/protocol/schema/BrowserCommand.json | 132 - .../protocol/schema/BrowserCommandCancel.json | 31 - .../schema/BrowserCommandResultParams.json | 82 - .../protocol/schema/BrowserDriverParams.json | 15 - .../schema/BrowserInventoryRequest.json | 54 - .../schema/BrowserInventoryResultParams.json | 88 - .../schema/BrowserProviderBindParams.json | 163 - .../schema/BrowserProviderBindResult.json | 23 - .../schema/BrowserProviderEventParams.json | 62 - .../schema/BrowserProviderRevoked.json | 27 - .../schema/BrowserProviderUnbindParams.json | 19 - .../protocol/schema/BrowserStatusResult.json | 18 - packages/protocol/schema/BudgetCapParams.json | 25 - packages/protocol/schema/BudgetState.json | 55 - packages/protocol/schema/CancelParams.json | 15 - .../protocol/schema/CapabilityRecord.json | 208 - packages/protocol/schema/CatalogResult.json | 69 - packages/protocol/schema/CatalogRevision.json | 17 - .../protocol/schema/CheckpointParams.json | 12 - .../protocol/schema/ClearHistoryParams.json | 17 - packages/protocol/schema/CommandParams.json | 27 - packages/protocol/schema/CommandResult.json | 95 - .../protocol/schema/CommandStatusParams.json | 15 - .../protocol/schema/CompactionListResult.json | 29 - .../protocol/schema/CompactionParams.json | 15 - .../protocol/schema/CompactionResult.json | 74 - .../schema/CompactionRetryResult.json | 18 - .../schema/CompactionSettingsResult.json | 21 - .../protocol/schema/CompletionParams.json | 30 - .../protocol/schema/CompletionResult.json | 47 - .../protocol/schema/ComputerAppParams.json | 15 - .../protocol/schema/ComputerStatusResult.json | 59 - .../protocol/schema/ConfigurationUpdate.json | 136 - .../protocol/schema/ContentEventPayload.json | 254 - packages/protocol/schema/ContentHandle.json | 31 - .../protocol/schema/ContentReadParams.json | 32 - .../protocol/schema/ContentReadResult.json | 49 - .../protocol/schema/ContextAuditResult.json | 40 - .../protocol/schema/CreateSessionParams.json | 39 - packages/protocol/schema/DefinitionList.json | 46 - .../protocol/schema/DefinitionParams.json | 18 - .../protocol/schema/DefinitionRecord.json | 422 - .../schema/DefinitionRegisterParams.json | 406 - .../schema/DefinitionRegisterResult.json | 23 - packages/protocol/schema/EffortParams.json | 19 - packages/protocol/schema/EffortResult.json | 15 - packages/protocol/schema/Empty.json | 7 - packages/protocol/schema/EmptyParams.json | 7 - .../protocol/schema/EventNotification.json | 38 - .../protocol/schema/ExecutorBindParams.json | 38 - .../protocol/schema/ExecutorBindResult.json | 36 - .../schema/ExecutorPendingParams.json | 25 - .../schema/ExecutorPendingResult.json | 281 - packages/protocol/schema/ForkParams.json | 26 - packages/protocol/schema/GatewayStatus.json | 21 - .../protocol/schema/GoalContextParams.json | 12 - packages/protocol/schema/GoalResult.json | 15 - .../protocol/schema/HistoryPageParams.json | 48 - .../protocol/schema/HookInvokeParams.json | 210 - .../protocol/schema/HookResultParams.json | 110 - .../protocol/schema/HostAttentionParams.json | 22 - .../protocol/schema/HostAttentionResult.json | 411 - .../protocol/schema/HostDirectoryParams.json | 27 - .../schema/HostDirectoryPickParams.json | 12 - .../schema/HostDirectoryPickResult.json | 18 - .../protocol/schema/HostDirectoryResult.json | 53 - .../schema/HostSkillCompletionParams.json | 77 - .../schema/HostThemeResolveParams.json | 15 - packages/protocol/schema/IDParams.json | 15 - .../protocol/schema/InboxControlResult.json | 25 - .../protocol/schema/InboxRemoveParams.json | 21 - .../protocol/schema/InboxSteerParams.json | 25 - .../protocol/schema/InitializeParams.json | 36 - .../protocol/schema/InitializeResult.json | 218 - packages/protocol/schema/LSPListResult.json | 31 - packages/protocol/schema/LifecycleEvent.json | 346 - packages/protocol/schema/ListParams.json | 12 - packages/protocol/schema/MCPAttachParams.json | 69 - .../protocol/schema/MCPBrandIconsParams.json | 21 - .../protocol/schema/MCPBrandIconsResult.json | 18 - .../protocol/schema/MCPImportApplyParams.json | 24 - .../protocol/schema/MCPImportApplyResult.json | 27 - .../schema/MCPImportCandidatesParams.json | 12 - .../schema/MCPImportCandidatesResult.json | 61 - packages/protocol/schema/MCPImportParams.json | 19 - .../schema/MCPImportStatusResult.json | 27 - packages/protocol/schema/MCPListResult.json | 37 - .../protocol/schema/MCPRefreshResult.json | 146 - packages/protocol/schema/MCPServerParams.json | 15 - .../protocol/schema/MailboxInspection.json | 116 - packages/protocol/schema/MailboxPage.json | 176 - .../protocol/schema/MailboxPageParams.json | 65 - .../protocol/schema/MailboxReadParams.json | 23 - packages/protocol/schema/ModelParams.json | 25 - packages/protocol/schema/ModelResult.json | 22 - packages/protocol/schema/PathParams.json | 15 - packages/protocol/schema/PathResult.json | 15 - .../schema/PermissionConfigureParams.json | 15 - .../protocol/schema/PermissionDecision.json | 33 - .../schema/PermissionDecisionParams.json | 42 - .../schema/PermissionDecisionResult.json | 19 - .../schema/PermissionRulesResult.json | 60 - packages/protocol/schema/PingResult.json | 21 - .../schema/ProviderCatalogParams.json | 15 - .../schema/ProviderCatalogsResult.json | 173 - .../schema/ProviderConfiguration.json | 133 - .../protocol/schema/ProviderCreateParams.json | 87 - .../schema/ProviderDisconnectParams.json | 19 - .../protocol/schema/ProviderKeySetup.json | 26 - packages/protocol/schema/ProviderList.json | 173 - .../protocol/schema/ProviderListParams.json | 15 - .../schema/ProviderLoginBeginParams.json | 12 - .../schema/ProviderLoginCreateParams.json | 19 - .../protocol/schema/ProviderLoginList.json | 105 - .../protocol/schema/ProviderLoginParams.json | 15 - .../schema/ProviderLoginProjectParams.json | 19 - .../protocol/schema/ProviderLoginStatus.json | 90 - .../schema/ProviderLoginTeamParams.json | 19 - .../protocol/schema/ProviderNameParams.json | 15 - .../protocol/schema/ProviderRemoveParams.json | 19 - .../protocol/schema/ProviderRemoveResult.json | 18 - packages/protocol/schema/ProviderStatus.json | 75 - .../protocol/schema/ProviderUpdateParams.json | 80 - .../schema/ProviderValidateParams.json | 23 - .../schema/ProviderValidateResult.json | 94 - packages/protocol/schema/QueryParams.json | 19 - packages/protocol/schema/QueryResult.json | 44 - .../protocol/schema/QuestionAnswerParams.json | 53 - packages/protocol/schema/RPCError.json | 34 - packages/protocol/schema/ReplayParams.json | 24 - packages/protocol/schema/ReplayResult.json | 53 - packages/protocol/schema/Resolved.json | 248 - packages/protocol/schema/RestartNotice.json | 26 - packages/protocol/schema/RestartParams.json | 17 - packages/protocol/schema/RewindParams.json | 24 - packages/protocol/schema/RewindResult.json | 19 - .../protocol/schema/RootCollectionPage.json | 1931 - .../protocol/schema/RootCollectionParams.json | 58 - packages/protocol/schema/RootIDResult.json | 15 - packages/protocol/schema/RootParams.json | 15 - packages/protocol/schema/RootSnapshot.json | 1915 - .../protocol/schema/RunConfigureParams.json | 21 - .../protocol/schema/RuntimeConfiguration.json | 134 - .../protocol/schema/ScheduleCreateParams.json | 19 - .../protocol/schema/ScheduleDeleteParams.json | 15 - .../protocol/schema/ScheduleListResult.json | 37 - packages/protocol/schema/ScheduleResult.json | 15 - .../protocol/schema/SessionCatalogPage.json | 114 - .../protocol/schema/SessionCatalogParams.json | 65 - .../protocol/schema/SessionListResult.json | 103 - packages/protocol/schema/SessionMetadata.json | 33 - .../protocol/schema/SessionPreviewResult.json | 23 - .../schema/SessionSummariesParams.json | 21 - .../schema/SessionSummariesResult.json | 75 - .../schema/SessionTitleChangedParams.json | 15 - .../protocol/schema/SessionUpdateEvent.json | 39 - packages/protocol/schema/ShellParams.json | 15 - packages/protocol/schema/SnapshotParams.json | 15 - packages/protocol/schema/SpanPage.json | 100 - packages/protocol/schema/SpanRecord.json | 65 - packages/protocol/schema/StreamEvent.json | 218 - packages/protocol/schema/SubmitPayload.json | 161 - packages/protocol/schema/SubscribeParams.json | 25 - packages/protocol/schema/SubscribeResult.json | 21 - .../protocol/schema/SubscriptionFailure.json | 54 - .../protocol/schema/TerminalAttachParams.json | 21 - .../protocol/schema/TerminalAttachResult.json | 39 - .../schema/TerminalDetachedParams.json | 15 - .../protocol/schema/TerminalExitedParams.json | 22 - .../protocol/schema/TerminalIDParams.json | 15 - .../protocol/schema/TerminalInputParams.json | 24 - .../protocol/schema/TerminalOpenParams.json | 25 - .../protocol/schema/TerminalOpenResult.json | 23 - .../protocol/schema/TerminalOutputParams.json | 30 - .../protocol/schema/TerminalResizeParams.json | 23 - .../protocol/schema/TerminalWriteParams.json | 24 - packages/protocol/schema/TextParams.json | 15 - packages/protocol/schema/TextResult.json | 16 - packages/protocol/schema/TitleParams.json | 15 - packages/protocol/schema/TitleResult.json | 15 - packages/protocol/schema/ToolCallParams.json | 17 - .../protocol/schema/ToolCancelParams.json | 25 - .../protocol/schema/ToolConfigureParams.json | 15 - .../protocol/schema/ToolInvokeParams.json | 53 - .../protocol/schema/ToolProgressParams.json | 25 - .../protocol/schema/ToolResultParams.json | 25 - .../protocol/schema/ToolSchemaResult.json | 40 - .../protocol/schema/TraceExportParams.json | 18 - .../protocol/schema/TraceExportResult.json | 48 - packages/protocol/schema/TracePageParams.json | 29 - .../protocol/schema/UnsubscribeParams.json | 15 - .../protocol/schema/UploadBeginParams.json | 38 - .../protocol/schema/UploadChunkParams.json | 30 - .../protocol/schema/UploadFinishParams.json | 15 - .../protocol/schema/UserHistoryResult.json | 12 - packages/protocol/schema/fixtures.json | 1562 - packages/protocol/schema/manifest.json | 1280 - packages/protocol/scripts/check.mjs | 15 + packages/protocol/scripts/generate.mjs | 13 +- .../protocol/scripts/initialization.test.mjs | 92 + packages/sdk/README.md | 15 +- packages/sdk/package.json | 3 +- packages/sdk/scripts/package-smoke.mjs | 8 +- scripts/docker/onboarding.Dockerfile | 12 +- .../docker/onboarding.Dockerfile.dockerignore | 2 + scripts/pack-web.mjs | 2 + scripts/pack-web.test.mjs | 10 + scripts/test-publish-whipcode.py | 17 +- scripts/update-local.mjs | 3 +- 259 files changed, 785 insertions(+), 165459 deletions(-) create mode 100644 apps/mobile/scripts/eas-build-post-install.mjs create mode 100644 apps/mobile/scripts/eas-build-post-install.test.mjs delete mode 100644 packages/protocol/generated/index.d.ts delete mode 100644 packages/protocol/generated/index.js delete mode 100644 packages/protocol/generated/request-validators.js delete mode 100644 packages/protocol/generated/response-validators.js delete mode 100644 packages/protocol/schema/Accepted.json delete mode 100644 packages/protocol/schema/AgentCancelParams.json delete mode 100644 packages/protocol/schema/AgentInputParams.json delete mode 100644 packages/protocol/schema/AgentListResult.json delete mode 100644 packages/protocol/schema/AgentSubmitResult.json delete mode 100644 packages/protocol/schema/AgentTranscriptResult.json delete mode 100644 packages/protocol/schema/ArchiveParams.json delete mode 100644 packages/protocol/schema/ArchiveResult.json delete mode 100644 packages/protocol/schema/BoundedTranscriptPage.json delete mode 100644 packages/protocol/schema/BrowserCommand.json delete mode 100644 packages/protocol/schema/BrowserCommandCancel.json delete mode 100644 packages/protocol/schema/BrowserCommandResultParams.json delete mode 100644 packages/protocol/schema/BrowserDriverParams.json delete mode 100644 packages/protocol/schema/BrowserInventoryRequest.json delete mode 100644 packages/protocol/schema/BrowserInventoryResultParams.json delete mode 100644 packages/protocol/schema/BrowserProviderBindParams.json delete mode 100644 packages/protocol/schema/BrowserProviderBindResult.json delete mode 100644 packages/protocol/schema/BrowserProviderEventParams.json delete mode 100644 packages/protocol/schema/BrowserProviderRevoked.json delete mode 100644 packages/protocol/schema/BrowserProviderUnbindParams.json delete mode 100644 packages/protocol/schema/BrowserStatusResult.json delete mode 100644 packages/protocol/schema/BudgetCapParams.json delete mode 100644 packages/protocol/schema/BudgetState.json delete mode 100644 packages/protocol/schema/CancelParams.json delete mode 100644 packages/protocol/schema/CapabilityRecord.json delete mode 100644 packages/protocol/schema/CatalogResult.json delete mode 100644 packages/protocol/schema/CatalogRevision.json delete mode 100644 packages/protocol/schema/CheckpointParams.json delete mode 100644 packages/protocol/schema/ClearHistoryParams.json delete mode 100644 packages/protocol/schema/CommandParams.json delete mode 100644 packages/protocol/schema/CommandResult.json delete mode 100644 packages/protocol/schema/CommandStatusParams.json delete mode 100644 packages/protocol/schema/CompactionListResult.json delete mode 100644 packages/protocol/schema/CompactionParams.json delete mode 100644 packages/protocol/schema/CompactionResult.json delete mode 100644 packages/protocol/schema/CompactionRetryResult.json delete mode 100644 packages/protocol/schema/CompactionSettingsResult.json delete mode 100644 packages/protocol/schema/CompletionParams.json delete mode 100644 packages/protocol/schema/CompletionResult.json delete mode 100644 packages/protocol/schema/ComputerAppParams.json delete mode 100644 packages/protocol/schema/ComputerStatusResult.json delete mode 100644 packages/protocol/schema/ConfigurationUpdate.json delete mode 100644 packages/protocol/schema/ContentEventPayload.json delete mode 100644 packages/protocol/schema/ContentHandle.json delete mode 100644 packages/protocol/schema/ContentReadParams.json delete mode 100644 packages/protocol/schema/ContentReadResult.json delete mode 100644 packages/protocol/schema/ContextAuditResult.json delete mode 100644 packages/protocol/schema/CreateSessionParams.json delete mode 100644 packages/protocol/schema/DefinitionList.json delete mode 100644 packages/protocol/schema/DefinitionParams.json delete mode 100644 packages/protocol/schema/DefinitionRecord.json delete mode 100644 packages/protocol/schema/DefinitionRegisterParams.json delete mode 100644 packages/protocol/schema/DefinitionRegisterResult.json delete mode 100644 packages/protocol/schema/EffortParams.json delete mode 100644 packages/protocol/schema/EffortResult.json delete mode 100644 packages/protocol/schema/Empty.json delete mode 100644 packages/protocol/schema/EmptyParams.json delete mode 100644 packages/protocol/schema/EventNotification.json delete mode 100644 packages/protocol/schema/ExecutorBindParams.json delete mode 100644 packages/protocol/schema/ExecutorBindResult.json delete mode 100644 packages/protocol/schema/ExecutorPendingParams.json delete mode 100644 packages/protocol/schema/ExecutorPendingResult.json delete mode 100644 packages/protocol/schema/ForkParams.json delete mode 100644 packages/protocol/schema/GatewayStatus.json delete mode 100644 packages/protocol/schema/GoalContextParams.json delete mode 100644 packages/protocol/schema/GoalResult.json delete mode 100644 packages/protocol/schema/HistoryPageParams.json delete mode 100644 packages/protocol/schema/HookInvokeParams.json delete mode 100644 packages/protocol/schema/HookResultParams.json delete mode 100644 packages/protocol/schema/HostAttentionParams.json delete mode 100644 packages/protocol/schema/HostAttentionResult.json delete mode 100644 packages/protocol/schema/HostDirectoryParams.json delete mode 100644 packages/protocol/schema/HostDirectoryPickParams.json delete mode 100644 packages/protocol/schema/HostDirectoryPickResult.json delete mode 100644 packages/protocol/schema/HostDirectoryResult.json delete mode 100644 packages/protocol/schema/HostSkillCompletionParams.json delete mode 100644 packages/protocol/schema/HostThemeResolveParams.json delete mode 100644 packages/protocol/schema/IDParams.json delete mode 100644 packages/protocol/schema/InboxControlResult.json delete mode 100644 packages/protocol/schema/InboxRemoveParams.json delete mode 100644 packages/protocol/schema/InboxSteerParams.json delete mode 100644 packages/protocol/schema/InitializeParams.json delete mode 100644 packages/protocol/schema/InitializeResult.json delete mode 100644 packages/protocol/schema/LSPListResult.json delete mode 100644 packages/protocol/schema/LifecycleEvent.json delete mode 100644 packages/protocol/schema/ListParams.json delete mode 100644 packages/protocol/schema/MCPAttachParams.json delete mode 100644 packages/protocol/schema/MCPBrandIconsParams.json delete mode 100644 packages/protocol/schema/MCPBrandIconsResult.json delete mode 100644 packages/protocol/schema/MCPImportApplyParams.json delete mode 100644 packages/protocol/schema/MCPImportApplyResult.json delete mode 100644 packages/protocol/schema/MCPImportCandidatesParams.json delete mode 100644 packages/protocol/schema/MCPImportCandidatesResult.json delete mode 100644 packages/protocol/schema/MCPImportParams.json delete mode 100644 packages/protocol/schema/MCPImportStatusResult.json delete mode 100644 packages/protocol/schema/MCPListResult.json delete mode 100644 packages/protocol/schema/MCPRefreshResult.json delete mode 100644 packages/protocol/schema/MCPServerParams.json delete mode 100644 packages/protocol/schema/MailboxInspection.json delete mode 100644 packages/protocol/schema/MailboxPage.json delete mode 100644 packages/protocol/schema/MailboxPageParams.json delete mode 100644 packages/protocol/schema/MailboxReadParams.json delete mode 100644 packages/protocol/schema/ModelParams.json delete mode 100644 packages/protocol/schema/ModelResult.json delete mode 100644 packages/protocol/schema/PathParams.json delete mode 100644 packages/protocol/schema/PathResult.json delete mode 100644 packages/protocol/schema/PermissionConfigureParams.json delete mode 100644 packages/protocol/schema/PermissionDecision.json delete mode 100644 packages/protocol/schema/PermissionDecisionParams.json delete mode 100644 packages/protocol/schema/PermissionDecisionResult.json delete mode 100644 packages/protocol/schema/PermissionRulesResult.json delete mode 100644 packages/protocol/schema/PingResult.json delete mode 100644 packages/protocol/schema/ProviderCatalogParams.json delete mode 100644 packages/protocol/schema/ProviderCatalogsResult.json delete mode 100644 packages/protocol/schema/ProviderConfiguration.json delete mode 100644 packages/protocol/schema/ProviderCreateParams.json delete mode 100644 packages/protocol/schema/ProviderDisconnectParams.json delete mode 100644 packages/protocol/schema/ProviderKeySetup.json delete mode 100644 packages/protocol/schema/ProviderList.json delete mode 100644 packages/protocol/schema/ProviderListParams.json delete mode 100644 packages/protocol/schema/ProviderLoginBeginParams.json delete mode 100644 packages/protocol/schema/ProviderLoginCreateParams.json delete mode 100644 packages/protocol/schema/ProviderLoginList.json delete mode 100644 packages/protocol/schema/ProviderLoginParams.json delete mode 100644 packages/protocol/schema/ProviderLoginProjectParams.json delete mode 100644 packages/protocol/schema/ProviderLoginStatus.json delete mode 100644 packages/protocol/schema/ProviderLoginTeamParams.json delete mode 100644 packages/protocol/schema/ProviderNameParams.json delete mode 100644 packages/protocol/schema/ProviderRemoveParams.json delete mode 100644 packages/protocol/schema/ProviderRemoveResult.json delete mode 100644 packages/protocol/schema/ProviderStatus.json delete mode 100644 packages/protocol/schema/ProviderUpdateParams.json delete mode 100644 packages/protocol/schema/ProviderValidateParams.json delete mode 100644 packages/protocol/schema/ProviderValidateResult.json delete mode 100644 packages/protocol/schema/QueryParams.json delete mode 100644 packages/protocol/schema/QueryResult.json delete mode 100644 packages/protocol/schema/QuestionAnswerParams.json delete mode 100644 packages/protocol/schema/RPCError.json delete mode 100644 packages/protocol/schema/ReplayParams.json delete mode 100644 packages/protocol/schema/ReplayResult.json delete mode 100644 packages/protocol/schema/Resolved.json delete mode 100644 packages/protocol/schema/RestartNotice.json delete mode 100644 packages/protocol/schema/RestartParams.json delete mode 100644 packages/protocol/schema/RewindParams.json delete mode 100644 packages/protocol/schema/RewindResult.json delete mode 100644 packages/protocol/schema/RootCollectionPage.json delete mode 100644 packages/protocol/schema/RootCollectionParams.json delete mode 100644 packages/protocol/schema/RootIDResult.json delete mode 100644 packages/protocol/schema/RootParams.json delete mode 100644 packages/protocol/schema/RootSnapshot.json delete mode 100644 packages/protocol/schema/RunConfigureParams.json delete mode 100644 packages/protocol/schema/RuntimeConfiguration.json delete mode 100644 packages/protocol/schema/ScheduleCreateParams.json delete mode 100644 packages/protocol/schema/ScheduleDeleteParams.json delete mode 100644 packages/protocol/schema/ScheduleListResult.json delete mode 100644 packages/protocol/schema/ScheduleResult.json delete mode 100644 packages/protocol/schema/SessionCatalogPage.json delete mode 100644 packages/protocol/schema/SessionCatalogParams.json delete mode 100644 packages/protocol/schema/SessionListResult.json delete mode 100644 packages/protocol/schema/SessionMetadata.json delete mode 100644 packages/protocol/schema/SessionPreviewResult.json delete mode 100644 packages/protocol/schema/SessionSummariesParams.json delete mode 100644 packages/protocol/schema/SessionSummariesResult.json delete mode 100644 packages/protocol/schema/SessionTitleChangedParams.json delete mode 100644 packages/protocol/schema/SessionUpdateEvent.json delete mode 100644 packages/protocol/schema/ShellParams.json delete mode 100644 packages/protocol/schema/SnapshotParams.json delete mode 100644 packages/protocol/schema/SpanPage.json delete mode 100644 packages/protocol/schema/SpanRecord.json delete mode 100644 packages/protocol/schema/StreamEvent.json delete mode 100644 packages/protocol/schema/SubmitPayload.json delete mode 100644 packages/protocol/schema/SubscribeParams.json delete mode 100644 packages/protocol/schema/SubscribeResult.json delete mode 100644 packages/protocol/schema/SubscriptionFailure.json delete mode 100644 packages/protocol/schema/TerminalAttachParams.json delete mode 100644 packages/protocol/schema/TerminalAttachResult.json delete mode 100644 packages/protocol/schema/TerminalDetachedParams.json delete mode 100644 packages/protocol/schema/TerminalExitedParams.json delete mode 100644 packages/protocol/schema/TerminalIDParams.json delete mode 100644 packages/protocol/schema/TerminalInputParams.json delete mode 100644 packages/protocol/schema/TerminalOpenParams.json delete mode 100644 packages/protocol/schema/TerminalOpenResult.json delete mode 100644 packages/protocol/schema/TerminalOutputParams.json delete mode 100644 packages/protocol/schema/TerminalResizeParams.json delete mode 100644 packages/protocol/schema/TerminalWriteParams.json delete mode 100644 packages/protocol/schema/TextParams.json delete mode 100644 packages/protocol/schema/TextResult.json delete mode 100644 packages/protocol/schema/TitleParams.json delete mode 100644 packages/protocol/schema/TitleResult.json delete mode 100644 packages/protocol/schema/ToolCallParams.json delete mode 100644 packages/protocol/schema/ToolCancelParams.json delete mode 100644 packages/protocol/schema/ToolConfigureParams.json delete mode 100644 packages/protocol/schema/ToolInvokeParams.json delete mode 100644 packages/protocol/schema/ToolProgressParams.json delete mode 100644 packages/protocol/schema/ToolResultParams.json delete mode 100644 packages/protocol/schema/ToolSchemaResult.json delete mode 100644 packages/protocol/schema/TraceExportParams.json delete mode 100644 packages/protocol/schema/TraceExportResult.json delete mode 100644 packages/protocol/schema/TracePageParams.json delete mode 100644 packages/protocol/schema/UnsubscribeParams.json delete mode 100644 packages/protocol/schema/UploadBeginParams.json delete mode 100644 packages/protocol/schema/UploadChunkParams.json delete mode 100644 packages/protocol/schema/UploadFinishParams.json delete mode 100644 packages/protocol/schema/UserHistoryResult.json delete mode 100644 packages/protocol/schema/fixtures.json delete mode 100644 packages/protocol/schema/manifest.json create mode 100644 packages/protocol/scripts/check.mjs create mode 100644 packages/protocol/scripts/initialization.test.mjs diff --git a/.easignore b/.easignore index dd5f3f538..b297ddef6 100644 --- a/.easignore +++ b/.easignore @@ -9,7 +9,9 @@ driver/.build/ internal/tui/whip-transcript-*.md -# TypeScript clients: generated contracts are tracked, build output is not. +# Cloud builds generate protocol artifacts from the included Go sources. +/packages/protocol/schema/ +/packages/protocol/generated/ node_modules/ packages/sdk/dist/ packages/sdk/build/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 691c66848..6290f36c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,6 +197,10 @@ jobs: node-version: 24 cache: npm - run: npm ci + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - run: npm audit --omit=dev --audit-level=high - run: npm run check - name: Web application and component checks @@ -350,6 +354,10 @@ jobs: - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: ci-renderer diff --git a/.github/workflows/desktop-check.yml b/.github/workflows/desktop-check.yml index 5ff360497..1f1c33ab3 100644 --- a/.github/workflows/desktop-check.yml +++ b/.github/workflows/desktop-check.yml @@ -26,6 +26,10 @@ jobs: - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - run: node node_modules/electron/install.js - run: npx playwright install ffmpeg - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index d52bfea2e..0191f3be8 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -63,6 +63,10 @@ jobs: - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - run: node node_modules/electron/install.js - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml index 7c48f8282..9d2dee3a7 100644 --- a/.github/workflows/mobile.yml +++ b/.github/workflows/mobile.yml @@ -20,11 +20,21 @@ jobs: - uses: actions/checkout@v7 with: ref: ${{ github.sha }} + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true - uses: actions/setup-node@v7 with: node-version: 24 cache: npm - run: npm ci + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build + - name: EAS initialization hook checks + run: node --test apps/mobile/scripts/eas-build-post-install.test.mjs - name: Mobile types and shared SDK build run: npm run check:mobile - name: Mobile behavior tests diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index f647c5331..ccef652b2 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -127,6 +127,10 @@ jobs: node-version: '24' cache: npm - run: npm ci + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: ci-renderer @@ -217,6 +221,10 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: '24' + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: pattern: whipcode-bin-* @@ -234,6 +242,10 @@ jobs: run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - name: Assemble and verify the exact complete release inventory run: | node scripts/build-installers.mjs "$RELEASE_TAG" candidate @@ -282,9 +294,17 @@ jobs: with: node-version: '24' cache: npm + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: release-candidate diff --git a/.gitignore b/.gitignore index 30f5343a7..822d23802 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,9 @@ driver/.build/ internal/tui/whip-transcript-*.md -# TypeScript clients: generated contracts are tracked, build output is not. +# Protocol artifacts and client build output are prepared with task generate. +/packages/protocol/schema/ +/packages/protocol/generated/ node_modules/ packages/sdk/dist/ packages/sdk/build/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 210afdbf7..ff6d9178f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,6 +3,27 @@ Thanks for contributing to whip. This doc covers what CI runs on your pull request and how to run the same checks locally before you push. +## Initialize the client workspace + +Use Node 24, the Go toolchain in `go.mod`, and Task. From the repository root: + +```sh +npm ci +task generate +``` + +`task generate` generates the protocol schemas, manifest, interoperability +fixtures, validators and declarations from Go, then builds the SDK. Both +`packages/protocol/schema/` and `packages/protocol/generated/` are ignored; +edit the Go definitions or generators instead of their output. Rerun +`task generate` after pulling, switching branches, or changing protocol source. +Run `npm ci` first when dependencies change. Ordinary builds and development +commands use the prepared files without regenerating them. `npm run check` +checks freshness without rewriting output and reports how to refresh it. + +Protocol-dependent CI jobs initialize once before their checks. Docs and UI-only +workflows keep their own setup and do not require protocol generation. + ## Before you push Run the local Go/runtime gate: @@ -95,7 +116,7 @@ Dependabot keeps Go modules and GitHub Actions current (grouped weekly PRs). ## Development and release boundaries -Use `npm ci && task build` for the packaged `./whipcode`, or `task install` for +After initialization, use `task build` for the packaged `./whipcode`, or `task install` for GOBIN/GOPATH/bin. There is no separate `whip` build or identity-specific task. Read [setup](docs/setup.md) and [frontend architecture](docs/frontend.md) before changing the affected area. Run the focused workspace tests too; CI supplies the diff --git a/README.md b/README.md index fc68c7475..880e40351 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,11 @@ Requires **Go 1.27+, Node.js 24, and [Task](https://taskfile.dev/)**. git clone --branch main https://github.com/context-labs/whip.git cd whip npm ci +task generate task build ``` -This builds locally without replacing an installed app or restarting its daemon. See the [development and setup guide](docs/setup.md), [Desktop guide](docs/desktop.md), and [contributor checks](CONTRIBUTING.md). +`task generate` prepares the ignored protocol artifacts and SDK. Rerun it after protocol changes or switching branches; rerun `npm ci` first when dependencies change. This builds locally without replacing an installed app or restarting its daemon. See the [development and setup guide](docs/setup.md), [Desktop guide](docs/desktop.md), and [contributor checks](CONTRIBUTING.md). [Documentation](docs/README.md) · [Architecture](docs/architecture.md) · [Frontend](docs/frontend.md) · [Evaluations](evals/README.md) diff --git a/Taskfile.yaml b/Taskfile.yaml index d6ad68dd1..e7053fb67 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -10,6 +10,12 @@ tasks: cmds: [task --list] silent: true + generate: + desc: Generate local protocol artifacts and build the SDK (run npm ci first; rerun after protocol changes) + cmds: + - npm run generate + - npm run build + run: desc: "Run whipcode locally from source (pass flags via CLI_ARGS: task run -- -m glm-5.2-fast)" interactive: true @@ -112,7 +118,7 @@ tasks: - go test -race ./internal/llm ./internal/session ./internal/agent ./internal/daemon ./internal/tui -run '^(TestModel|TestPricing|TestUsage|TestStreamPreserves|TestStreamUnterminated|TestCompletePreserves|TestMalformedUsage)' contract: - desc: "Validate generated Node 24 contracts and deterministic generation (run npm ci first)" + desc: "Validate local protocol artifacts and deterministic generation (run task generate first)" cmds: - npm run check -w @whip/protocol diff --git a/apps/docs/src/content/docs/typescript-sdk/index.mdx b/apps/docs/src/content/docs/typescript-sdk/index.mdx index f64ec6e75..8aec1fe86 100644 --- a/apps/docs/src/content/docs/typescript-sdk/index.mdx +++ b/apps/docs/src/content/docs/typescript-sdk/index.mdx @@ -12,13 +12,15 @@ Use the SDK to run tasks, observe sessions, or serve agents with your own tools. `@whip/sdk` is currently a private ESM workspace package in the [whip repository](https://github.com/context-labs/whip/tree/main/packages/sdk). It is not a public npm package. Use Node.js 24 and a matching whip daemon; keep the SDK and host versions together. -From a source checkout: +From a source checkout, install the Go toolchain specified in `go.mod` and [Task](https://taskfile.dev/), then run: ```bash npm ci -npm run build -w @whip/sdk +task generate ``` +`task generate` creates the protocol artifacts from Go and builds the SDK. These outputs are ignored by Git. Rerun it after pulling, switching branches, or changing protocol source; rerun `npm ci` first when dependencies change. + Place the `.mts` examples below in the checkout so Node can resolve its workspace packages. Node 24 runs these examples directly; for example, `node run.mts`. | Import | Use | diff --git a/apps/mobile/README.md b/apps/mobile/README.md index 1641170eb..0a9b3e91c 100644 --- a/apps/mobile/README.md +++ b/apps/mobile/README.md @@ -8,12 +8,18 @@ URLs. See [setup and development](../../docs/mobile.md), the canonical Run workspace commands from the repository root: ```sh +npm ci +task generate npm run check:mobile npm run test:mobile npm run export:mobile npm run dev:mobile ``` +Use Node 24, the Go toolchain in `go.mod`, and Task. `task generate` prepares +ignored protocol artifacts and builds the SDK. Rerun it after pulling, switching +branches, or changing protocol source; rerun `npm ci` first when dependencies change. + A native development build is required. Expo Go cannot provide the encrypted storage/native UI modules. Native projects are generated from `app.config.ts`; `modules/whip-storage` contains the small backup-exclusion bridge. diff --git a/apps/mobile/package.json b/apps/mobile/package.json index f1cf614bb..078d98980 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -47,7 +47,7 @@ "typescript": "6.0.3" }, "scripts": { - "eas-build-post-install": "npm run build -w @whip/sdk", + "eas-build-post-install": "node scripts/eas-build-post-install.mjs", "start": "expo start --dev-client", "ios": "expo run:ios", "android": "expo run:android", diff --git a/apps/mobile/scripts/eas-build-post-install.mjs b/apps/mobile/scripts/eas-build-post-install.mjs new file mode 100644 index 000000000..b5d159106 --- /dev/null +++ b/apps/mobile/scripts/eas-build-post-install.mjs @@ -0,0 +1,47 @@ +// EAS supplies Node (eas.json), but its images do not guarantee Go. Initialize +// once here after dependency installation; normal npm installs do not run this. +import assert from 'node:assert/strict'; +import { execFileSync, spawnSync } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = fileURLToPath(new URL('../../../', import.meta.url)); +const version = /^go (\d+\.\d+\.\d+)$/m.exec(await readFile(path.join(root, 'go.mod'), 'utf8'))?.[1]; +assert(version, 'Cannot read the Go version from go.mod'); +const env = { ...process.env, GOTOOLCHAIN: 'local' }; +let temporary; +const run = (command, args) => execFileSync(command, args, { cwd: root, env, stdio: 'inherit' }); +const goVersion = () => spawnSync('go', ['env', 'GOVERSION'], { cwd: root, env, encoding: 'utf8' }).stdout?.trim(); +async function download(url) { + const response = await fetch(url, { signal: AbortSignal.timeout(120_000) }); + if (!response.ok) throw new Error(`Go download failed: ${url} (${response.status})`); + return response; +} + +try { + if (goVersion() !== `go${version}`) { + assert(['darwin', 'linux'].includes(process.platform), `Unsupported EAS host: ${process.platform}`); + const arch = { x64: 'amd64', arm64: 'arm64' }[process.arch]; + assert(arch, `Unsupported EAS architecture: ${process.arch}`); + const url = `https://dl.google.com/go/go${version}.${process.platform}-${arch}.tar.gz`; + console.log(`Installing Go ${version} for protocol generation`); + const checksum = (await (await download(`${url}.sha256`)).text()).trim(); + const bytes = Buffer.from(await (await download(url)).arrayBuffer()); + assert(/^[a-f0-9]{64}$/.test(checksum) && createHash('sha256').update(bytes).digest('hex') === checksum, + 'Go archive checksum does not match'); + temporary = await mkdtemp(path.join(tmpdir(), 'whip-eas-go-')); + const archive = path.join(temporary, 'go.tar.gz'); + await writeFile(archive, bytes); + run('tar', ['-xzf', archive, '-C', temporary]); + env.GOROOT = path.join(temporary, 'go'); + env.PATH = `${path.join(env.GOROOT, 'bin')}${path.delimiter}${env.PATH ?? ''}`; + } + assert.equal(goVersion(), `go${version}`, 'EAS must use the Go version from go.mod'); + run('npm', ['run', 'generate']); + run('npm', ['run', 'build']); +} finally { + if (temporary) await rm(temporary, { recursive: true, force: true }); +} diff --git a/apps/mobile/scripts/eas-build-post-install.test.mjs b/apps/mobile/scripts/eas-build-post-install.test.mjs new file mode 100644 index 000000000..d2b10d5bd --- /dev/null +++ b/apps/mobile/scripts/eas-build-post-install.test.mjs @@ -0,0 +1,67 @@ +import assert from 'node:assert/strict'; +import { execFileSync, spawnSync } from 'node:child_process'; +import { copyFile, mkdir, mkdtemp, readFile, realpath, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; +import test from 'node:test'; + +test('EAS initializes from source with verified Go and stops on failures', async () => { + const root = await realpath(await mkdtemp(path.join(tmpdir(), 'whip-eas-init-test-'))); + try { + const scripts = path.join(root, 'apps/mobile/scripts'); + const bin = path.join(root, 'bin'); + const source = path.join(root, 'archive/go/bin'); + await Promise.all([mkdir(scripts, { recursive: true }), mkdir(bin), mkdir(source, { recursive: true })]); + await copyFile(new URL('./eas-build-post-install.mjs', import.meta.url), path.join(scripts, 'eas-build-post-install.mjs')); + await writeFile(path.join(root, 'go.mod'), 'module fixture\n\ngo 1.2.3\n'); + await writeFile(path.join(bin, 'go'), '#!/bin/sh\nprintf "%s\\n" "$FAKE_GO_VERSION"\n', { mode: 0o755 }); + await writeFile(path.join(source, 'go'), '#!/bin/sh\nprintf "go1.2.3\\n"\n', { mode: 0o755 }); + await writeFile(path.join(bin, 'npm'), `#!/bin/sh +printf '%s|%s|%s\n' "$PWD" "$*" "$(go env GOVERSION)" >> "$FAKE_NPM_LOG" +if [ "$FAIL_GENERATE" = 1 ] && [ "$*" = 'run generate' ]; then exit 7; fi +`, { mode: 0o755 }); + const archive = path.join(root, 'go.tar.gz'); + execFileSync('tar', ['-czf', archive, '-C', path.join(root, 'archive'), 'go']); + const preload = path.join(root, 'download.mjs'); + await writeFile(preload, ` +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { readFile } from 'node:fs/promises'; +const bytes = await readFile(process.env.FAKE_GO_ARCHIVE); +const url = 'https://dl.google.com/go/go1.2.3.' + process.platform + '-' + ({ x64: 'amd64', arm64: 'arm64' }[process.arch]) + '.tar.gz'; +globalThis.fetch = async actual => { + assert.notEqual(process.env.FORBID_DOWNLOAD, '1', 'Existing exact Go must not download'); + assert([url, url + '.sha256'].includes(actual)); + if (process.env.FAIL_DOWNLOAD === '1') return new Response('', { status: 503 }); + const checksum = process.env.BAD_CHECKSUM === '1' ? '0'.repeat(64) : createHash('sha256').update(bytes).digest('hex'); + return new Response(actual.endsWith('.sha256') ? checksum : bytes); +}; +`); + for (const scenario of [ + { name: 'existing', env: { FAKE_GO_VERSION: 'go1.2.3', FORBID_DOWNLOAD: '1' }, commands: ['run generate', 'run build'] }, + { name: 'download', commands: ['run generate', 'run build'] }, + { name: 'checksum', env: { BAD_CHECKSUM: '1' }, error: /Go archive checksum/, commands: [] }, + { name: 'network', env: { FAIL_DOWNLOAD: '1' }, error: /Go download failed/, commands: [] }, + { name: 'generation', env: { FAIL_GENERATE: '1' }, error: /npm run generate/, commands: ['run generate'] }, + ]) { + const log = path.join(root, `${scenario.name}.log`); + const result = spawnSync(process.execPath, ['--import', preload, path.join(scripts, 'eas-build-post-install.mjs')], { + cwd: path.join(root, 'apps/mobile'), encoding: 'utf8', + env: { ...process.env, PATH: `${bin}:/usr/bin:/bin`, FAKE_GO_VERSION: 'go0.0.0', + FAKE_GO_ARCHIVE: archive, FAKE_NPM_LOG: log, ...scenario.env }, + }); + const details = `${scenario.name}: ${result.stdout}\n${result.stderr}`; + if (scenario.error) { + assert.notEqual(result.status, 0, details); + assert.match(result.stderr, scenario.error, details); + } else assert.equal(result.status, 0, details); + const lines = (await readFile(log, 'utf8').catch(error => { + if (error.code === 'ENOENT') return ''; + throw error; + })).trim().split('\n').filter(Boolean); + assert.deepEqual(lines, scenario.commands.map(command => `${root}|${command}|go1.2.3`), details); + } + } finally { + await rm(root, { recursive: true, force: true }); + } +}); diff --git a/apps/web/scripts/settings.mjs b/apps/web/scripts/settings.mjs index d5738b614..14892cc92 100644 --- a/apps/web/scripts/settings.mjs +++ b/apps/web/scripts/settings.mjs @@ -110,41 +110,71 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await expect(page.getByRole('heading', { name: label, exact: true })).toBeVisible(); await expect(page.getByRole('button', { name: /^Attention ·/ })).toHaveCount(0); if (label === 'Agents & execution') { - await expect(page.locator('#compact_model')).toContainText('Automatic'); - await expect(page.locator('#compact_percent')).toContainText('50%'); - await expect(page.getByRole('button', { name: 'Custom summary model', exact: true })).toBeHidden(); - await page.getByRole('button', { name: 'Advanced compaction settings', exact: true }).click(); - await select('Summary model mode', 'Custom'); - await page.getByRole('button', { name: 'Custom summary model', exact: true }).click(); + const model = page.getByRole('button', { name: 'Summary model', exact: true }); + const percentage = page.getByRole('combobox', { name: 'Compact at', exact: true }); + await expect(model).toHaveText('Conversation Model'); + await expect(percentage).toHaveText('50%'); + await expect(page.getByText('Summarize older context while keeping the full conversation history.', { exact: true })).toHaveCount(0); + const spacing = await page.evaluate(() => { + const measure = (firstId, secondId) => { + const row = document.getElementById(firstId), next = document.getElementById(secondId); + const section = row.closest('section'), panel = section.lastElementChild; + const rowBox = row.getBoundingClientRect(), panelBox = panel.getBoundingClientRect(); + const rowStyle = getComputedStyle(row), panelStyle = getComputedStyle(panel); + return { + top: rowBox.top - panelBox.top, left: rowBox.left - panelBox.left, + gap: next.getBoundingClientRect().top - rowBox.bottom, + panelPadding: panelStyle.padding, headingGap: getComputedStyle(section).gap, + rowPadding: rowStyle.padding, divider: rowStyle.borderBottom, + labelSize: getComputedStyle(document.getElementById(firstId + '-label')).fontSize, + }; + }; + return { compaction: measure('compact_model', 'compact_percent'), limits: measure('goal_max_rounds', 'max_retries') }; + }); + for (const [key, value] of Object.entries(spacing.compaction)) { + const expected = spacing.limits[key]; + // Allow browser subpixel rounding, but not a visible spacing difference. + assert.ok(typeof value === 'number' ? Math.abs(value - expected) < 0.1 : value === expected, 'Compaction spacing differs from neighboring settings: ' + key); + } + await expect(page.getByRole('button', { name: 'Advanced compaction settings', exact: true })).toHaveCount(0); + await model.click(); + await expect(page.getByRole('option', { name: 'Conversation Model', exact: true })).toBeVisible(); await page.getByRole('option', { name: 'settings-model · openrouter', exact: true }).click(); - await select('Compaction timing', 'Custom'); - const percentage = page.getByRole('spinbutton', { name: 'Context window percentage', exact: true }); - await percentage.fill('65'); + await expect(model).toContainText('openrouter'); + await percentage.click(); + await expect(page.getByRole('option')).toHaveCount(9); + await page.getByRole('option', { name: '70%', exact: true }).click(); await page.getByRole('button', { name: 'Save host defaults', exact: true }).click(); await expect(page.getByRole('button', { name: 'Save host defaults', exact: true })).toBeDisabled(); let savedCompaction = JSON.parse((await readFile(join(fixture.directory, 'home', 'config.json'), 'utf8')).replace(/^\/\/[^\n]*\n/gm, '')); assert.equal(savedCompaction.compactModel, 'settings-model'); assert.equal(savedCompaction.compactProvider, 'openrouter'); - assert.equal(savedCompaction.compactPct, 65); + assert.equal(savedCompaction.compactPct, 70); await auditServers('main'); await page.locator('#compact_model').scrollIntoViewIfNeeded(); await page.screenshot({ path: join(results, engine + '-compaction-custom.png') }); - await select('Summary model mode', 'Automatic'); - await select('Compaction timing', 'Automatic · 50%'); + await model.click(); + await page.getByRole('textbox', { name: 'Search models' }).fill('no-matching-model'); + await page.keyboard.press('ArrowDown'); + await expect(page.getByRole('option', { name: 'Conversation Model', exact: true })).toBeFocused(); + await page.keyboard.press('Enter'); + await expect(model).toBeFocused(); + await select('Compact at', '50%'); await page.getByRole('button', { name: 'Save host defaults', exact: true }).click(); await expect(page.getByRole('button', { name: 'Save host defaults', exact: true })).toBeDisabled(); savedCompaction = JSON.parse((await readFile(join(fixture.directory, 'home', 'config.json'), 'utf8')).replace(/^\/\/[^\n]*\n/gm, '')); assert.equal(savedCompaction.compactModel ?? '', ''); assert.equal(savedCompaction.compactProvider ?? '', ''); - assert.equal(savedCompaction.compactPct ?? 0, 0); - await page.getByRole('button', { name: 'Advanced compaction settings', exact: true }).click(); - await page.setViewportSize({ width: 390, height: 844 }); - await expect(page.locator('#compact_model')).toContainText('Automatic'); - assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'Compaction settings overflow on mobile'); - await page.locator('#compact_model').scrollIntoViewIfNeeded(); - await page.screenshot({ path: join(results, engine + '-compaction-automatic-narrow.png') }); + assert.equal(savedCompaction.compactPct, 50); + for (const width of [1440, 390, 320]) { + await page.setViewportSize({ width, height: 1080 }); + await expect(model).toHaveText('Conversation Model'); + assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'Compaction settings overflow at ' + width); + await page.locator('#compact_model').scrollIntoViewIfNeeded(); + await page.screenshot({ path: join(results, engine + '-compaction-' + width + '.png') }); + } await page.setViewportSize({ width: 1440, height: 1080 }); - checks.push('automatic compaction, connected custom model/provider, threshold, reset, and mobile reflow'); + checks.push('two compaction controls, connected route, nine percentages, keyboard default reset, raw saved values, and 320px reflow'); } if (label === 'Servers') { await expect(page.getByRole('heading', { name: 'Servers', exact: true })).toHaveCount(1); @@ -224,10 +254,10 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await expect(page.locator('html')).toHaveAttribute('data-theme', 'claude-code'); await page.screenshot({ path: join(results, `${engine}-appearance-dark.png`) }); await category('Agents & execution').click(); - await expect(page.locator('#compact_model')).toContainText('Automatic'); + await expect(page.locator('#compact_model')).toContainText('Conversation Model'); await page.locator('#compact_model').scrollIntoViewIfNeeded(); await auditServers('main'); - await page.screenshot({ path: join(results, engine + '-compaction-automatic-dark.png') }); + await page.screenshot({ path: join(results, engine + '-compaction-conversation-dark.png') }); await category('Servers').click(); await auditServers('main'); await page.screenshot({ path: join(results, `${engine}-servers-dark.png`) }); @@ -336,6 +366,37 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await themeSearch.press('Escape'); await page.screenshot({ path: join(results, `${engine}-appearance-narrow.png`) }); checks.push('1024/768/767/390/320 widths, narrow category search keyboard focus, and maximum UI size reflow'); + await page.getByRole('button', { name: 'Appearance', exact: true }).click(); + await page.getByRole('dialog', { name: 'Settings', exact: true }).getByRole('button', { name: 'Agents & execution', exact: true }).click(); + const compactModel = page.getByRole('button', { name: 'Summary model', exact: true }); + await expect(compactModel).toHaveText('Conversation Model'); + assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), 'Compaction large text overflow at 320px'); + await page.locator('#compact_model').scrollIntoViewIfNeeded(); + await page.screenshot({ path: join(results, engine + '-compaction-large-text-320.png') }); + await compactModel.click(); + const compactList = page.getByRole('listbox', { name: 'Models', exact: true }); + assert.ok(await compactList.evaluate(element => { const box = element.getBoundingClientRect(); return box.left >= 0 && box.right <= innerWidth && element.scrollWidth <= element.clientWidth; }), 'Compaction model menu overflow'); + await page.getByRole('textbox', { name: 'Search models' }).press('Escape'); + await expect(compactModel).toBeFocused(); + await page.setViewportSize({ width: 1440, height: 1080 }); + await page.goto(chatURL + '?panel=context'); + const inspector = page.getByRole('dialog', { name: 'Session details', exact: true }); + await expect(inspector).toBeVisible(); + await select('Context settings section', 'Compaction'); + await expect(inspector.getByRole('button', { name: 'Summary model', exact: true })).toHaveText('Conversation Model'); + await expect(inspector.getByRole('combobox', { name: 'Compact at', exact: true })).toHaveText('50%'); + await expect(inspector.getByText(/shared host defaults/)).toBeVisible(); + assert.ok(await inspector.evaluate(element => element.scrollWidth <= element.clientWidth), 'Compaction inspector overflows'); + const controlGeometry = await inspector.evaluate(element => { + const group = element.querySelector('#compact_model'); + const control = group.querySelector('button'); + const label = group.querySelector('#compact_model-label'); + return { width: control.getBoundingClientRect().width, labelBottom: label.getBoundingClientRect().bottom, controlTop: control.getBoundingClientRect().top }; + }); + assert.ok(controlGeometry.width >= 200 && controlGeometry.controlTop >= controlGeometry.labelBottom, 'Narrow inspector should stack controls at readable widths'); + await page.screenshot({ path: join(results, engine + '-compaction-inspector.png') }); + checks.push('compaction at maximum text size/320px, focused searchable menu, and stacked shared controls in a narrow inspector'); + assert.deepEqual(errors, [], 'Browser runtime errors'); assert.deepEqual(await page.evaluate(() => window.cspErrors), [], 'Production CSP violations'); await writeFile(join(results, `${engine}.json`), JSON.stringify({ engine, checks, pageErrors: errors, cspErrors: [], frameCount: frames.length }, null, 2)); diff --git a/docs/README.md b/docs/README.md index c015fde46..e4437f1e7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -40,6 +40,7 @@ whip defaults to inference.net models; the `inf` CLI provisions the key: ```sh git clone --branch main https://github.com/context-labs/whip && cd whip npm ci +task generate # protocol artifacts and SDK task install # packaged whipcode; Go 1.27+, Node 24, Task bun add -g @inference/cli # the inf CLI diff --git a/docs/agent-loop.md b/docs/agent-loop.md index 128392645..85e2c5b94 100644 --- a/docs/agent-loop.md +++ b/docs/agent-loop.md @@ -31,7 +31,7 @@ request without making them inaccessible. Proactive compaction runs when the provider-reported prompt usage (or a token estimate when usage is unavailable) crosses the configured fraction of the -conversation model's window. Automatic uses 50%; custom host thresholds accept +conversation model's window. The default is 50%; custom host thresholds accept 10–90%. A provider context-limit error may trigger one reactive compaction and retry. Compaction summaries and raw-history cutoffs are committed with the turn. diff --git a/docs/desktop.md b/docs/desktop.md index 8c5d0293b..dd9e343b8 100644 --- a/docs/desktop.md +++ b/docs/desktop.md @@ -347,16 +347,22 @@ installed-editor diagnostic requires explicit opt-in. ## Build and develop -Building requires macOS arm64, Node 24, Go from `go.mod`, and Xcode command-line +Building requires macOS arm64, Node 24, Go from `go.mod`, Task, and Xcode command-line tools for Swift/signing. The resulting app includes Electron, Go and the computer helper; users do not need those build toolchains or a first-launch runtime download. ```sh npm ci +task generate node node_modules/electron/install.js npm run dev:desktop ``` +`task generate` prepares ignored protocol artifacts and builds the SDK before +desktop scripts import them. Rerun it after pulling, switching branches, or editing +protocol source; rerun `npm ci` first when dependencies change. Development and +build commands use the prepared files, while packaging checks their freshness. + For UI development against an already-running daemon, use attach mode: ```sh diff --git a/docs/features.md b/docs/features.md index e20d6b793..2e5e5689f 100644 --- a/docs/features.md +++ b/docs/features.md @@ -137,11 +137,12 @@ Available modules are summarized in [tools.md](tools.md). bounded summary. - `context.inspect/search/read` returns source metadata and byte spans. - Proactive and reactive compaction protect the provider context window. - Automatic uses each agent's conversation model/provider, with no auxiliary - account requirement. An omitted model and zero threshold mean Automatic (50%); + Conversation Model uses each agent's conversation model/provider, with no auxiliary + account requirement. An omitted model and zero threshold use the defaults (50%); existing saved custom routes are preserved. Host settings and the idle-session - inspector reuse the catalog model/provider picker; custom thresholds accept - 10–90%. Missing or too-small custom routes and definite safe request rejections + inspector share two controls: a model/provider picker with Conversation Model + and a Compact at selector offering 10–90% in ten-point increments. Missing or + too-small custom routes and definite safe request rejections can fall back to the conversation route, with a notice and the actual route and reason on the summary's trace. Cancellation, uncertain completion, partial output and accounting/budget failures never cause a second-route replay. diff --git a/docs/frontend.md b/docs/frontend.md index 706f9ab01..1a7838d49 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1297,14 +1297,23 @@ host-owned. API-key entry is an ephemeral UI input: never place it in drafts, Query persistence, command-recovery storage, or logs. Configuration updates use revision checks; display conflicts instead of overwriting newer settings. -Compaction settings are automatic-first. An empty summary model means each -conversation uses its own model/provider; zero threshold means Automatic (50%), -not disabled. Existing saved model overrides remain custom. Show the effective -threshold in the summary rows and put overrides in the shared Collapsible. Custom -summary selection reuses CatalogModelPicker so model/provider are one choice, not -independent text inputs; custom thresholds use 10–90%. The host settings and idle -session inspector share this selection contract and preserve revision-checked -drafts. They describe saved defaults, not a live effective route. Actual summary +Compaction settings expose two controls: Summary model defaults to Conversation +Model, and Compact at defaults to 50%, with 10–90% choices in ten-point increments. +No Advanced disclosure or separate Automatic/Custom modes. Conversation Model is +an optional first-class choice in CatalogModelPicker; selecting it clears both +model and provider, while explicit choices select a connected pair. Open the +picker to load its host-scoped catalog; keep the default choice available on +catalog failures and while searching. Show provider identity in the closed control. +Zero remains the stored default sentinel; never dirty a form by displaying it as +50%. Preserve non-ten/out-of-range saved percentages and unavailable routes until +explicitly changed. The backend continues accepting integers from 10–90%. +Host settings and the inspector share these controls and preserve revision-checked +drafts. They describe host defaults, not a live effective route or a session-only +override; explicit agent-definition compaction settings still take precedence. +The Conversation Model label requires the paired updated execution host: older +hosts interpreted empty model as DeepSeek. The current handshake does not prove +support, so display a short compatibility note rather than guessing from protocol +version or a dev build. Actual summary model/provider and any compaction fallback are read from the existing call trace; do not add a second client routing resolver or history store. `settings/provider-connections.tsx` reads the inexpensive `provider.list` @@ -2634,6 +2643,16 @@ accepts additive incoming fields, and surfaces unknown event kinds explicitly. Malformed known messages are protocol errors. Feature components must not create their own WebSocket clients or handwritten JSON-RPC envelopes. +Go protocol definitions and generators are the authored contract. Both +`packages/protocol/schema/` (schemas, manifest and interoperability fixtures) and +`packages/protocol/generated/` (JavaScript and declarations) are ignored build +output. Initialize with `npm ci` and `task generate` before client development. +The task runs Go-to-schema generation, then validator/declaration generation and +SDK compilation. Ordinary builds consume the prepared files; they do not generate +the protocol. Freshness checks compare local output with current source without +rewriting it. Package archives contain ready-to-use JavaScript and declarations, +so archive consumers do not need Go or a generator. + The browser uses the gateway's WebSocket API and scoped HTTP content transfers. The gateway relays the existing protocol to the socket-only daemon; it owns no execution engine, store, or independent HTTP business API. @@ -2748,11 +2767,11 @@ Useful starting files: ## Development and validation -Run from the repository root with Node 24 and the Go toolchain in `go.mod`. +Run from the repository root with Node 24, the Go toolchain in `go.mod`, and Task. ```sh npm ci -npm run build # SDK artifacts used by the app +task generate # protocol artifacts and SDK used by the app # In another terminal, run a gateway for the intended compatible daemon: # WHIPCODE_LISTEN=127.0.0.1:4444 whipcode web --no-open # Attaches through the local dev proxy; no daemon restart. @@ -2767,6 +2786,12 @@ The proxy accepts only local requests from the exact dev origin, then rewrites the upstream origin for HTTP content and WebSockets. It does not start or reconfigure a gateway or daemon. Shared app/UI source edits use React Fast Refresh; SDK source edits still require `npm run build`. +Rerun `task generate` after pulling, switching branches, or editing protocol +definitions/generators; rerun `npm ci` first when dependencies change. Development +launches do not automatically detect protocol drift. `npm run check` and packaging +freshness checks reject stale or missing artifacts and direct you to refresh them. +Protocol-dependent CI jobs initialize once before checks. Docs/UI-only workflows +remain independent and do not need protocol generation. Use [web-app.md](web-app.md) for daemon/gateway setup, production assets, trusted-network access, and troubleshooting. A daemon restart interrupts work; do not restart or reset a developer's runtime as a diff --git a/docs/mobile-release.md b/docs/mobile-release.md index 043b0387e..8be90cf32 100644 --- a/docs/mobile-release.md +++ b/docs/mobile-release.md @@ -53,7 +53,7 @@ is the toolchain reference; current attempt results belong in the evidence recor [mobile.yml](../.github/workflows/mobile.yml) runs on the root CI workflow and contributes to its required `go` aggregate gate. It has read-only repository -permissions, uses Node 24 and the root npm lockfile, and runs mobile TypeScript, +permissions, uses Node 24, Go from `go.mod` and the root npm lockfile, and runs mobile TypeScript, Jest, pinned Expo Doctor 1.20.4 and production Metro exports for both platforms. It can also be dispatched manually. It does not contact a Whip host, provision Tailscale, start an EAS build or submit a binary. @@ -62,12 +62,17 @@ Reproduce from the repository root: ```sh npm ci +task generate npm run check:mobile npm run test:mobile npm exec --yes --package=expo-doctor@1.20.4 -- expo-doctor apps/mobile npm run export:mobile ``` +CI initializes the protocol artifacts and SDK once after dependency installation, +using the same generation/build commands as `task generate`. Refresh local output +after pulling, switching branches, or changing protocol source before these checks. + Exports prove JavaScript bundling and package resolution. They do not compile Swift/Kotlin/C++, test SQLCipher on a device, exercise the native UI or establish signing/distribution. Existing SDK, web, daemon and package checks remain in @@ -99,9 +104,14 @@ See [Expo's local development commands](https://docs.expo.dev/more/expo-cli/). ## EAS profiles and reproducibility [eas.json](../apps/mobile/eas.json) pins EAS CLI 23.2.0 and Node 24.14.1. Always run -EAS from `apps/mobile`. The app's `eas-build-post-install` hook builds `@whip/sdk` -before Metro uses its generated exports; a clean cloud checkout has no local -`packages/sdk/dist`. Preserve the root lockfile and this workspace build step. +EAS from `apps/mobile`. The app's `eas-build-post-install` hook runs +[`scripts/eas-build-post-install.mjs`](../apps/mobile/scripts/eas-build-post-install.mjs) +after dependency installation. It uses the exact Go version from `go.mod`, +downloading an official archive and verifying its checksum/version when the +installed version does not match. It then runs root `npm run generate` and +`npm run build` before Metro consumes the protocol and SDK exports. A downloaded +toolchain is temporary and removed afterward. Preserve the root lockfile and this +initialization step; it does not reinstall dependencies or add a root npm hook. See [monorepo setup](https://docs.expo.dev/build-reference/build-with-monorepos/) and [build lifecycle hooks](https://docs.expo.dev/build-reference/npm-hooks/). @@ -122,9 +132,11 @@ npx --yes eas-cli@23.2.0 build:inspect --platform ios --profile preview-simulato ``` Run this from `apps/mobile` and choose an unused output directory. Confirm the -root lockfile, all workspace sources and local native module are included, while -generated native projects, nested native-module build output, credentials and -local test data are excluded. EAS runs +root lockfile, all workspace sources, local native module, `go.mod`, `go.sum`, +Go generator and its module sources are included. +Both `packages/protocol/schema/` and `packages/protocol/generated/`, SDK build +output, generated native projects, nested native-module build output, credentials +and local test data must be excluded. EAS runs Prebuild on the uploaded source; it does not use the local ignored Xcode project. See [EAS upload exclusions](https://docs.expo.dev/build-reference/easignore/). diff --git a/docs/mobile.md b/docs/mobile.md index 79ce45cc5..a391c0d0d 100644 --- a/docs/mobile.md +++ b/docs/mobile.md @@ -140,17 +140,21 @@ catalogs refer to the execution computer, not the phone filesystem. ## Development -Use the repository's Node 24/npm workspace and root lockfile: +Use Node 24, the Go toolchain in `go.mod`, Task, and the root npm lockfile: ```sh npm ci -npm run build +task generate npm run check:mobile npm run test:mobile npm run export:mobile npm run dev:mobile ``` +`task generate` prepares the ignored protocol artifacts and SDK. Rerun it after +pulling, switching branches, or editing protocol source; rerun `npm ci` first +when dependencies change. Mobile commands consume the initialized workspace. + Use a development client, not Expo Go: SQLCipher, Expo UI and the private storage module require a native build. From `apps/mobile`, `npx expo run:ios` or `npx expo run:android` generates and builds native projects. `ios/`, `android/`, diff --git a/docs/models-providers.md b/docs/models-providers.md index de22a2266..705e1caf0 100644 --- a/docs/models-providers.md +++ b/docs/models-providers.md @@ -379,7 +379,7 @@ and conversation model menus include discovered models and identify the provider for each choice, including when API and subscription routes share a model name. Automatic compaction and titles follow the conversation's subscription route. Existing saved custom compaction routes remain separate overrides; reset Summary -model to Automatic under Settings → Agents & execution → Context compaction to +model to Conversation Model under Settings → Agents & execution → Context compaction to follow the conversation again. The adapter uses streamed Responses with `store:false`. Text, images on @@ -499,25 +499,35 @@ a charge or the route is known to be free. ## Compaction model -Compaction is **Automatic** by default: each agent summarizes older active +Compaction uses **Conversation Model** by default: each agent summarizes older active context using its own conversation model and provider. It needs no additional provider connection and does not delete the raw transcript. Automatic session titles use the same route selection. -An empty or omitted `compactModel` selects Automatic; `compactProvider` is then -ignored. Existing explicitly saved models, including the former DeepSeek default, -remain custom overrides. In Settings → Agents & execution, use **Advanced -compaction settings** to select a custom model/provider together from the existing -catalog picker, or reset to Automatic. Settings saves are revision-checked and -apply when a runtime is created or reloaded; the session inspector can apply the -host defaults and reload its idle session. `/compact <model> [provider]` also -selects a custom summarizer. - -`compactPct: 0` (or omitted) means Automatic, currently **50%** of the conversation -model's context window. Custom thresholds accept integers from **10–90%**. This -controls when to summarize, not a compression ratio. Older saved out-of-range -values remain loadable and use their existing clamped effective threshold; new -edits must use the supported range. Provider-reported prompt usage drives the +An empty or omitted `compactModel` selects **Conversation Model**; `compactProvider` +is then ignored. Existing explicitly saved models, including the former DeepSeek +default, remain custom overrides. In Settings → Agents & execution, **Summary +model** directly selects Conversation Model or a connected model/provider pair +from the catalog picker. There is no Advanced disclosure or separate mode switch. +Settings saves are revision-checked and apply when a runtime is created or +reloaded; the session inspector can save the same host defaults and reload its +idle session. Agent-definition overrides still take precedence. The /compact +command also selects a custom summarizer. + +Update the execution host together with this UI. Older hosts interpreted an empty +summary model as the built-in DeepSeek route; the current protocol/build metadata +does not reliably distinguish those semantics. A compatibility note remains visible +when Conversation Model is selected. Do not reset explicit DeepSeek configurations +merely because that model was once the default. + +`compactPct: 0` (or omitted) uses the default, currently **50%** of the conversation +model's context window. **Compact at** offers 10%, 20%, … 90%. Existing saved +non-ten percentages remain visible and unchanged until explicitly edited, and +out-of-range values display their clamped effective threshold. The API continues +to accept any integer in 10–90%, or zero for the default. Unrelated saves preserve +the raw zero/legacy values. An explicit new 50% selection saves 50 unless returning +to the unchanged zero default. This is a trigger, not a compression ratio. +Provider-reported prompt usage drives the trigger, with an estimate when usage is unavailable. If the context window is unknown, only reactive context-limit recovery applies. @@ -527,7 +537,7 @@ summary. Runtime fallback is bounded and only follows a definite safe rejection, not uncertain completion, partial output, cancellation, or accounting/budget failure. Both attempted routes retain normal accounting. A notice explains a fallback, and the successful summary's trace records the actual model/provider -and fallback reason. Automatic never selects another vendor or ranks models by +and fallback reason. Conversation Model never selects another vendor or ranks models by price. Mechanics: [agent-loop.md](agent-loop.md#context-focusing). ## Read next diff --git a/docs/protocol-v2.md b/docs/protocol-v2.md index 5dfb5e2c4..ba55fa79b 100644 --- a/docs/protocol-v2.md +++ b/docs/protocol-v2.md @@ -11,9 +11,12 @@ The executable contract is `internal/protocol`: wire DTOs, operation registry, permission metadata and schemas. `packages/protocol/schema/manifest.json` lists RPCs and runtime operations with their parameter/result types. Generated TypeScript declarations and Ajv validators are exported by `@whip/protocol`. -Run `npm ci` and `npm run check` from the repository root. Regenerate after -editing Go types with `npm run generate`; drift checks compare without rewriting -files. Standalone validators require no runtime code generation or Ajv dependency. +Run `npm ci`, `task generate`, then `npm run check` from the repository root. +Both `packages/protocol/schema/` and `packages/protocol/generated/` are ignored +output; Go definitions and generators are the source of truth. Refresh with +`task generate` after pulling, switching branches, or editing protocol source. +Drift checks compare local output with current source without rewriting files. +Standalone validators require no runtime code generation or Ajv dependency. Typed RPC/runtime maps classify query, durable and ephemeral operations. The handwritten `@whip/sdk` consumes this contract; see [SDK usage](../packages/sdk/README.md). @@ -534,6 +537,7 @@ active daemon. It runs the **built SDK**, not a second handwritten RPC client: ```sh npm ci +task generate npx playwright install chromium firefox npm run test:browser WHIP_SDK_RACE=1 npm run acceptance diff --git a/docs/setup.md b/docs/setup.md index eb4354d3e..f9bcff39c 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -39,10 +39,19 @@ Or build the packaged CLI from source with Go 1.27+, Node 24, and Task: git clone --branch main https://github.com/context-labs/whip.git cd whip npm ci +task generate # protocol artifacts and SDK used by the app task build # ./whipcode, including the embedded renderer/native helper task install # install into GOBIN or GOPATH/bin ``` +`task generate` prepares the client workspace from the authored Go protocol +definitions. Its schemas, manifest, test fixtures, validators and declarations +are generated locally and ignored by Git. Run it again after pulling, switching +branches, or editing protocol definitions/generators; run `npm ci` first when npm +dependencies change. Ordinary builds use those prepared artifacts. Validation +and packaging reject missing or stale protocol output with refresh instructions. +The independent docs site does not need this generation step or Go. + On macOS, the native helper also requires Xcode command-line tools. Bare `go install .../cmd/whip@latest` is not the supported product build: it names the wrong executable and omits required packaged assets. Local builds use `dev` @@ -281,8 +290,9 @@ npm run update:local ``` This updates the existing `/Applications/Whip.app` and its saved `whipcode` -executable (falling back to `/usr/local/bin/whipcode`). It runs `npm ci`, builds -the web UI, Swift helper, Go backend and desktop app from the **current working +executable (falling back to `/usr/local/bin/whipcode`). It runs `npm ci`, generates +the protocol artifacts and SDK, then builds the web UI, Swift helper, Go backend +and desktop app from the **current working tree, including uncommitted changes**, then signs and verifies the package. It does not pull Git changes. Run `git pull` yourself first if desired. Signing failures stop packaging immediately and report the signer error, before @@ -394,4 +404,3 @@ docker stop <container-name> Run `task test:onboarding-docker` for the launcher and renderer provenance tests. Container source metadata is explicitly marked local; release builds retain their normal Git provenance checks and reject artifacts using that local override. - diff --git a/docs/web-app.md b/docs/web-app.md index 5ecbef02b..ffaf42337 100644 --- a/docs/web-app.md +++ b/docs/web-app.md @@ -259,10 +259,11 @@ access behind a trusted network or authenticated proxy. ## Build from source -Use Node 24 and the Go version declared in `go.mod`: +Use Node 24, the Go version declared in `go.mod`, and Task: ```sh npm ci +task generate task build ./whipcode daemon start ./whipcode web @@ -291,6 +292,10 @@ When replacing a running source-built daemon, use your rebuilt binary explicitly ## Develop against an existing daemon +Initialize with `npm ci` and `task generate` first. Rerun `task generate` after +pulling, switching branches, or editing protocol source; the protocol artifacts +are ignored and ordinary development/build commands do not refresh them. + For UI iteration, run `npm run dev:web` from the repository root and open `http://127.0.0.1:3000`. Vite reloads changes in `apps/web`, `packages/app` and `packages/ui`; `task update:local` is only needed to rebuild/install the packaged diff --git a/packages/app/src/compaction-settings.tsx b/packages/app/src/compaction-settings.tsx index e50e264cd..555fe25e0 100644 --- a/packages/app/src/compaction-settings.tsx +++ b/packages/app/src/compaction-settings.tsx @@ -1,24 +1,20 @@ import { useState } from 'react'; import type { WhipClient } from '@whip/sdk'; import type { ConfigurationUpdate, RuntimeConfiguration } from '@whip/protocol'; -import { Collapsible, Input, Select } from '@whip/ui'; +import { Select } from '@whip/ui'; import * as stylex from '@stylexjs/stylex'; import { CatalogModelPicker, useProviderCatalog } from './model-selection'; -import { SettingRow, settingsSection } from './settings/section-layout'; +import { SettingRow } from './settings/section-layout'; import { layout } from './styles'; -const styles = stylex.create({ summary: { minWidth: 0, overflowWrap: 'anywhere' } }); +const styles = stylex.create({ + container: { containerType: 'inline-size' }, + control: { width: { default: 300, '@container (max-width: 560px)': '100%' }, maxWidth: '100%', minWidth: 0, flexShrink: 0 }, +}); -// Keep invalid input text in the draft; numeric zero is reserved for Automatic. -export type CompactionValues = Pick<RuntimeConfiguration, 'compact_model' | 'compact_provider'> & { compact_percent: number | string }; - -export function compactionError(value: CompactionValues, base: CompactionValues): string | undefined { - if (value.compact_percent === base.compact_percent || value.compact_percent === 0) return; - const percent = Number(value.compact_percent); - if (!Number.isInteger(percent) || percent < 10 || percent > 90) { - return 'Use a whole-number percentage from 10 to 90, or choose Automatic.'; - } -} +export type CompactionValues = Pick<RuntimeConfiguration, 'compact_model' | 'compact_provider' | 'compact_percent'>; +const thresholds = Array.from({ length: 9 }, (_, index) => (index + 1) * 10); +const effectivePercent = (percent: number) => percent === 0 ? 50 : Math.max(10, Math.min(90, percent)); /** Omit untouched overrides so saving another setting never rewrites legacy values. */ export function compactionPatch(value: CompactionValues, base: CompactionValues): Pick<ConfigurationUpdate, 'compact_model' | 'compact_provider' | 'compact_percent'> { @@ -27,7 +23,7 @@ export function compactionPatch(value: CompactionValues, base: CompactionValues) compact_model: value.compact_model.trim(), compact_provider: value.compact_model.trim() ? value.compact_provider : '', } : {}), - ...(value.compact_percent !== base.compact_percent ? { compact_percent: Number(value.compact_percent) } : {}), + ...(value.compact_percent !== base.compact_percent ? { compact_percent: value.compact_percent } : {}), }; } @@ -36,13 +32,10 @@ export function CompactionSettings({ client, value, base, disabled, onChange }: client: WhipClient; value: CompactionValues; base: CompactionValues; disabled: boolean; onChange(value: CompactionValues): void; }) { - const [advanced, setAdvanced] = useState(false); - const [choosingModel, setChoosingModel] = useState(false); - const customModel = !!value.compact_model.trim(); - const customTiming = value.compact_percent !== 0; - const catalog = useProviderCatalog(client, !disabled && advanced && (customModel || choosingModel)); + const [openedModelPicker, setOpenedModelPicker] = useState(false); + const catalog = useProviderCatalog(client, !disabled && openedModelPicker); const result = catalog.data?.result; - // A custom override must select a known, connected route, not arbitrary provider text. + // Only offer connected routes; saved routes remain visible even when unavailable. const connected = (provider: string) => result?.providers[provider]?.available === true; const connectedCatalog = result && { ...result, @@ -50,51 +43,28 @@ export function CompactionSettings({ client, value, base, disabled, onChange }: [name, { ...model, providers: model.providers?.filter(connected) ?? [] }])), catalogs: Object.fromEntries(Object.entries(result.catalogs).filter(([provider]) => connected(provider))), }; - const percent = Number(value.compact_percent); - const effectivePercent = percent === 0 ? 50 : Math.max(10, Math.min(90, percent)); - const error = compactionError(value, base); - const legacyPercent = value.compact_percent === base.compact_percent && percent !== 0 && percent !== effectivePercent; - return <> - <p {...stylex.props(layout.muted)}>Older active context is summarized. Full conversation history remains available.</p> - <SettingRow id="compact_model" label="Summary model"> - <span {...stylex.props(styles.summary)}>{customModel ? `Custom · ${value.compact_model} · ${value.compact_provider || 'provider resolved by host'}` : 'Automatic · conversation model and provider'}</span> + const percent = value.compact_percent || 50; + const legacyPercent = !thresholds.includes(percent); + return <div {...stylex.props(layout.column, styles.container)}> + <SettingRow id="compact_model" label="Summary model" description={value.compact_model + ? 'Choose a model and provider for summaries.' : "Use each conversation’s model and provider."}> + <CatalogModelPicker settings showProvider label="Summary model" model={value.compact_model} provider={value.compact_provider} + defaultChoice={{ label: 'Conversation Model', description: 'Use each conversation’s model and provider.' }} + catalog={connectedCatalog} loading={catalog.isLoading} error={disabled ? undefined : catalog.error?.message} onRetry={() => void catalog.refetch()} + onOpen={() => setOpenedModelPicker(true)} + disabled={disabled} xstyle={styles.control} + onChange={(model, provider) => onChange({ ...value, compact_model: model, compact_provider: provider })} /> </SettingRow> - <SettingRow id="compact_percent" label="When to compact" - description={legacyPercent ? `Saved value: ${percent}%. The effective threshold is ${effectivePercent}%; saving other settings keeps the saved value.` : undefined}> - <span>{error ? 'Custom · choose 10–90%' : `${percent === 0 ? 'Automatic' : 'Custom'} · ${effectivePercent}%`}</span> + <SettingRow id="compact_percent" label="Compact at" description={legacyPercent && percent !== effectivePercent(percent) + ? 'Saved value: ' + percent + '%. The effective threshold is ' + effectivePercent(percent) + '%; kept until you change it.' + : 'Of the conversation model’s context window.'}> + <Select label="Compact at" value={String(percent)} disabled={disabled} xstyle={styles.control} + options={[ + ...(legacyPercent ? [{ value: String(percent), label: effectivePercent(percent) + '% (saved value)', disabled: true }] : []), + ...thresholds.map(percent => ({ value: String(percent), label: percent + '%' })), + ]} + onValueChange={next => onChange({ ...value, compact_percent: Number(next) === (base.compact_percent || 50) ? base.compact_percent : Number(next) })} /> </SettingRow> - <Collapsible title="Advanced compaction settings" open={advanced} onOpenChange={setAdvanced}> - <div {...stylex.props(layout.column)}> - <SettingRow id="compact_model_mode" label="Summary model override" description="Use the conversation model, or choose a connected model and provider together."> - <Select label="Summary model mode" value={customModel || choosingModel ? 'custom' : 'automatic'} disabled={disabled} xstyle={settingsSection.control} - options={[{ value: 'automatic', label: 'Automatic' }, { value: 'custom', label: 'Custom' }]} - onValueChange={mode => { - setChoosingModel(mode === 'custom'); - if (mode === 'automatic') onChange({ ...value, compact_model: '', compact_provider: '' }); - }} /> - </SettingRow> - {(customModel || choosingModel) && <SettingRow id="compact_custom_model" label="Custom summary model" - description="If this route is unavailable, the conversation model is used instead. Saved overrides stay unchanged until you edit them."> - <CatalogModelPicker settings label="Custom summary model" model={value.compact_model} provider={customModel ? value.compact_provider : ''} - catalog={connectedCatalog} loading={catalog.isLoading} error={disabled ? undefined : catalog.error?.message} onRetry={() => void catalog.refetch()} - disabled={disabled} xstyle={settingsSection.control} - onChange={(model, provider) => { setChoosingModel(false); onChange({ ...value, compact_model: model, compact_provider: provider }); }} /> - </SettingRow>} - <SettingRow id="compact_timing" label="Compaction timing"> - <Select label="Compaction timing" value={customTiming ? 'custom' : 'automatic'} disabled={disabled} xstyle={settingsSection.control} - options={[{ value: 'automatic', label: 'Automatic · 50%' }, { value: 'custom', label: 'Custom' }]} - onValueChange={mode => onChange({ ...value, compact_percent: mode === 'automatic' ? 0 : 50 })} /> - </SettingRow> - {customTiming && <SettingRow id="compact_custom_percent" label="Context window percentage" description="Compact when active context reaches this share of the model’s context window. Choose 10–90%."> - <Input aria-label="Context window percentage" type="number" min={10} max={90} step={1} disabled={disabled} - aria-invalid={!!error} aria-describedby={error ? 'compact-percent-error' : undefined} xstyle={settingsSection.control} - value={value.compact_percent} onChange={event => { - const next = event.target.valueAsNumber; - onChange({ ...value, compact_percent: Number.isInteger(next) && next >= 10 && next <= 90 ? next : event.target.value }); - }} /> - </SettingRow>} - {error && <p id="compact-percent-error" role="alert">{error}</p>} - </div> - </Collapsible> - </>; + {!value.compact_model && <p {...stylex.props(layout.muted)}>Conversation Model requires an up-to-date execution host; older hosts may use DeepSeek instead.</p>} + </div>; } diff --git a/packages/app/src/details/session-controls.tsx b/packages/app/src/details/session-controls.tsx index 905147f94..9157139da 100644 --- a/packages/app/src/details/session-controls.tsx +++ b/packages/app/src/details/session-controls.tsx @@ -6,7 +6,7 @@ import * as stylex from '@stylexjs/stylex'; import { useRuntime } from '../context'; import { layout } from '../styles'; import { ModelSelection } from '../model-selection'; -import { CompactionSettings, compactionError, compactionPatch, type CompactionValues } from '../compaction-settings'; +import { CompactionSettings, compactionPatch, type CompactionValues } from '../compaction-settings'; import { describeRule, splitGlobalRule } from '../permission-scope'; import { Action, @@ -422,7 +422,7 @@ export function Compaction(props: InspectorProps) { {(configuration.data || draft) && <CompactionSettings client={props.view.session.client} value={value} base={base} disabled={!props.connected || applying} onChange={edit} />} <Action - disabled={!props.connected || !idle || !configuration.data || applying || !!compactionError(value, base)} + disabled={!props.connected || !idle || !configuration.data || applying} run={async () => { setApplying(true); try { diff --git a/packages/app/src/model-selection.tsx b/packages/app/src/model-selection.tsx index 8be604423..bae9acc3b 100644 --- a/packages/app/src/model-selection.tsx +++ b/packages/app/src/model-selection.tsx @@ -121,9 +121,10 @@ export function ModelPicker({ view, root, connected }: ModelProps) { } /** The same catalog picker can edit a session or a settings draft. */ -export function CatalogModelPicker({ catalog, loading, error, model, provider, disabled, onChange, onRetry, label = 'Model', settings = false, onSessionOptions, xstyle }: { +export function CatalogModelPicker({ catalog, loading, error, model, provider, disabled, onChange, onRetry, label = 'Model', settings = false, defaultChoice, showProvider = false, onOpen, onSessionOptions, xstyle }: { catalog?: CatalogResult; loading?: boolean; error?: string; model: string; provider: string; disabled?: boolean; onChange(model: string, provider: string): void | Promise<unknown>; onRetry?(): void; label?: string; settings?: boolean; + defaultChoice?: { label: string; description: string }; showProvider?: boolean; onOpen?(): void; onSessionOptions?(): void; } & Styled) { const [open, setOpen] = useState(false); @@ -143,7 +144,9 @@ export function CatalogModelPicker({ catalog, loading, error, model, provider, d const ordered = searching || !selected ? filtered : [selected, ...filtered.filter(option => option.value !== current)]; - const pick = async (option: typeof options[number]) => { + const usingDefault = !!defaultChoice && !model.trim(); + const routeLabel = usingDefault ? defaultChoice.label : [model || 'Model unavailable', provider || (showProvider && model ? 'provider resolved by host' : '')].filter(Boolean).join(' · '); + const pick = async (option: { value: string; name: string; provider: string }) => { if (pending) return; if (option.value === current) { setOpen(false); return; } const id = ++generation.current; @@ -152,15 +155,24 @@ export function CatalogModelPicker({ catalog, loading, error, model, provider, d catch (error) { if (id === generation.current) setActionError(error); } finally { if (id === generation.current) setPending(false); } }; - return <Popover open={open} onOpenChange={value => { if (!pending) setOpen(value); }} xstyle={styles.popupWide} + return <Popover open={open} onOpenChange={value => { if (!pending) { setOpen(value); if (value) onOpen?.(); } }} xstyle={styles.popupWide} trigger={<Button variant={settings ? "secondary" : "ghost"} aria-label={label} disabled={disabled || pending} - title={`${model || 'Model unavailable'}${provider ? ` · ${provider}` : ''}`} + title={routeLabel} aria-description={routeLabel} xstyle={[styles.trigger, xstyle]}> - <ProviderLogo id={provider} size={14} /> - <span {...stylex.props(layout.ellipsis)}>{model || 'Choose model'}</span> + {!usingDefault && <ProviderLogo id={provider} size={14} />} + <span {...stylex.props(layout.ellipsis, showProvider && layout.grow)}>{usingDefault ? defaultChoice.label : model || 'Choose model'}</span> + {showProvider && !usingDefault && <span {...stylex.props(layout.ellipsis, styles.optionProvider)}>{provider || 'host-resolved'}</span>} <ChevronDown size={14} {...stylex.props(styles.chevron)} /> </Button>}> - {open && <div {...stylex.props(layout.column, styles.pickerList)}> + {open && <div {...stylex.props(layout.column, styles.pickerList)} onKeyDown={event => { + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; + const items = [...event.currentTarget.querySelectorAll<HTMLButtonElement>('[role="option"]:not(:disabled)')]; + if (!items.length) return; + event.preventDefault(); event.stopPropagation(); + const index = items.indexOf(event.target as HTMLButtonElement); + const next = index < 0 ? (event.key === 'ArrowDown' ? 0 : items.length - 1) : (index + (event.key === 'ArrowDown' ? 1 : items.length - 1)) % items.length; + items[next]?.focus(); + }}> <div {...stylex.props(styles.searchBox)}> <Search size={14} {...stylex.props(styles.searchIcon)} /> <input aria-label="Search models" placeholder="Search models" value={query} autoFocus @@ -168,7 +180,13 @@ export function CatalogModelPicker({ catalog, loading, error, model, provider, d onChange={event => setQuery(event.target.value)} /> </div> {actionError !== undefined && <ErrorNotice type="action" owner="model-selection" error={actionError} title="Could not change model" />} - <div role="listbox" aria-label="Models" aria-activedescendant={current} {...stylex.props(styles.list)}> + <div role="listbox" aria-label="Models" {...stylex.props(styles.list)}> + {defaultChoice && <button type="button" role="option" aria-label={defaultChoice.label} aria-selected={usingDefault} + disabled={disabled || pending} {...stylex.props(styles.option, styles.defaultOption)} + onClick={() => void pick({ value: JSON.stringify(['', '']), name: '', provider: '' })}> + <span {...stylex.props(layout.grow)}>{defaultChoice.label}<span {...stylex.props(styles.defaultDescription)}>{defaultChoice.description}</span></span> + <span aria-hidden {...stylex.props(styles.checkSlot)}>{usingDefault && <Check size={14} {...stylex.props(styles.check)} />}</span> + </button>} {loading && <p role="status" {...stylex.props(styles.listMeta)}>Loading models…</p>} {error && <ErrorNotice type="resource" owner="model-catalog" error={error} title="Could not load models" action={onRetry && <Button variant="ghost" onClick={onRetry}>Retry</Button>} />} {!loading && !error && !filtered.length && <p {...stylex.props(styles.listMeta)}>No matching models</p>} @@ -267,6 +285,8 @@ const styles = stylex.create({ list: { overflowY: 'auto', maxHeight: 320, minHeight: 0, paddingBottom: 12, maskImage: 'linear-gradient(to bottom, black calc(100% - 24px), transparent)', WebkitMaskImage: 'linear-gradient(to bottom, black calc(100% - 24px), transparent)' }, listMeta: { color: surface.secondaryText, fontSize: typography.size12, padding: 8, margin: 0 }, option: { display: 'flex', alignItems: 'center', gap: 12, width: '100%', paddingBlock: 7, paddingInline: 8, borderRadius: 6, borderWidth: 0, backgroundColor: { default: 'transparent', ':hover': colors.hover }, color: colors.foreground, font: 'inherit', fontSize: typography.size13, textAlign: 'start', cursor: 'default', minHeight: 30 }, + defaultOption: { borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: surface.quietBorder, borderRadius: 0, marginBottom: 4 }, + defaultDescription: { display: 'block', marginTop: 4, fontSize: typography.size12, color: surface.secondaryText }, optionProvider: { flexShrink: 0, maxWidth: '40%', textAlign: 'end', color: surface.secondaryText, fontSize: typography.size12 }, checkSlot: { display: 'flex', width: 14, flexShrink: 0 }, optionActive: { backgroundColor: colors.hover }, diff --git a/packages/app/src/settings/configuration.tsx b/packages/app/src/settings/configuration.tsx index 480a416c0..c5e4bba67 100644 --- a/packages/app/src/settings/configuration.tsx +++ b/packages/app/src/settings/configuration.tsx @@ -12,7 +12,7 @@ import { PermissionModeControl } from '../permission-mode'; import { layout } from '../styles'; import { SettingsGroup, SettingRow, settingsSection } from './section-layout'; import { useSettingsEdits } from './unsaved'; -import { CompactionSettings, compactionError, compactionPatch, type CompactionValues } from '../compaction-settings'; +import { CompactionSettings, compactionPatch, type CompactionValues } from '../compaction-settings'; type Category = 'providers' | 'execution'; const providerFields = ['default_model', 'default_provider', 'default_effort', 'default_permission_mode'] as const; @@ -87,8 +87,6 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider setError('Use non-negative whole numbers for goal rounds and retries.'); return; } - const compactError = category === 'execution' ? compactionError(value, base) : undefined; - if (compactError) { setErrorType('validation'); setError(compactError); return; } const result = await client.configuration.update(configurationPatch(category, value, base), { signal: controller.signal }); if (controller.signal.aborted) return; runtime.queries.setQueryData(queryKey, result); @@ -123,7 +121,6 @@ function ConfigurationForm({ client, config, enabled, category, defaultProvider value={Number.isNaN(field.state.value) ? '' : field.state.value} onBlur={field.handleBlur} onChange={event => field.handleChange(event.target.valueAsNumber)} /> </SettingRow>} </form.Field>; - // Validate only edited compaction values; native min/max would block untouched legacy defaults. return <form noValidate {...stylex.props(layout.column)} onSubmit={event => { event.preventDefault(); void form.handleSubmit(); }}> {category === 'providers' ? <SettingsGroup title="Defaults for new work"> <SettingRow id="default_model" label="Default model" description="Choose the model and provider for new work."> diff --git a/packages/app/src/settings/navigation.ts b/packages/app/src/settings/navigation.ts index 58d59fade..cf1fa517e 100644 --- a/packages/app/src/settings/navigation.ts +++ b/packages/app/src/settings/navigation.ts @@ -38,8 +38,8 @@ export const settingEntries: readonly SettingEntry[] = [ { id: 'default_model', section: 'providers', label: 'Default model', keywords: 'default provider model route' }, { id: 'default_effort', section: 'providers', label: 'Default reasoning effort', keywords: 'thinking low medium high' }, { id: 'default_permission_mode', section: 'providers', label: 'Default permission level', keywords: 'permissions approval ask full access automatic prompt' }, - { id: 'compact_model', section: 'execution', label: 'Summary model', keywords: 'context compaction summary provider automatic custom' }, - { id: 'compact_percent', section: 'execution', label: 'When to compact', keywords: 'context compaction threshold percentage automatic' }, + { id: 'compact_model', section: 'execution', label: 'Summary model', keywords: 'context compaction summary provider conversation model automatic custom' }, + { id: 'compact_percent', section: 'execution', label: 'Compact at', keywords: 'context compaction threshold percentage 50 automatic' }, { id: 'goal_max_rounds', section: 'execution', label: 'Goal rounds', keywords: 'agent limit execution' }, { id: 'max_retries', section: 'execution', label: 'Maximum retries', keywords: 'agent errors execution' }, { id: 'import_claude', section: 'execution', label: 'Import Claude configuration', keywords: 'integration' }, diff --git a/packages/app/test/inspector.test.tsx b/packages/app/test/inspector.test.tsx index ee3d8d1f9..16b406406 100644 --- a/packages/app/test/inspector.test.tsx +++ b/packages/app/test/inspector.test.tsx @@ -233,9 +233,8 @@ describe('session inspector controls', () => { new Error('configuration revision changed'), ); f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · original · provider'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + await screen.findByRole('button', { name: 'Summary model' }); + fireEvent.click(screen.getByRole('button', { name: 'Summary model' })); fireEvent.click(await screen.findByRole('option', { name: 'my-model · provider' })); act(() => f.queries.setQueryData(['inspector-compaction-config', 'runtime'], { @@ -637,18 +636,15 @@ it('explains unavailable live MCP refresh without sending an unsupported action' }); describe('compaction defaults', () => { - it('shows Automatic, chooses a connected pair, and explicitly reloads after saving', async () => { + it('shows Conversation Model, chooses a connected pair, and explicitly reloads after saving', async () => { const f = fixture(); f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: '', compact_provider: '', compact_percent: 0 }); f.render(<Compaction {...f.props} />); - expect(await screen.findByText('Automatic · conversation model and provider')).toBeDefined(); - expect(screen.getByText('Automatic · 50%')).toBeDefined(); + expect(await screen.findByText('Conversation Model')).toBeDefined(); + expect(screen.getByRole('combobox', { name: 'Compact at' })).toBeDefined(); expect(screen.queryByRole('combobox', { name: 'Summary model mode' })).toBeNull(); expect(f.client.providers.catalogs).not.toHaveBeenCalled(); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - fireEvent.click(screen.getByRole('combobox', { name: 'Summary model mode' })); - await userEvent.click(await screen.findByRole('option', { name: 'Custom', exact: true })); - fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + fireEvent.click(screen.getByRole('button', { name: 'Summary model' })); const option = await screen.findByRole('option', { name: 'my-model · provider' }); expect(screen.queryByRole('option', { name: 'offline-model · offline' })).toBeNull(); fireEvent.click(option); @@ -661,33 +657,21 @@ describe('compaction defaults', () => { expect(f.client.configuration.update.mock.invocationCallOrder[0]).toBeLessThan(f.client.submit.mock.invocationCallOrder[0]!); }); - it('clears both override fields on Automatic without changing the threshold', async () => { + it('clears both override fields on Conversation Model without changing the threshold', async () => { const f = fixture(); f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · original · provider'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - fireEvent.click(screen.getByRole('combobox', { name: 'Summary model mode' })); - await userEvent.click(await screen.findByRole('option', { name: 'Automatic', exact: true })); + await screen.findByRole('button', { name: 'Summary model' }); + fireEvent.click(screen.getByRole('button', { name: 'Summary model' })); + await userEvent.click(await screen.findByRole('option', { name: 'Conversation Model', exact: true })); fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); await waitFor(() => expect(f.run).toHaveBeenCalled()); expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_model: '', compact_provider: '' }); }); - it('validates thresholds and never applies settings to an active session', async () => { + it('never applies settings to an active session', async () => { const f = fixture(); - f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: 'original', compact_provider: 'provider', compact_percent: 60 }); + f.root.active_turns = { root: 'turn' } as unknown as RootSnapshot['active_turns']; f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · 60%'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - const percent = screen.getByRole('spinbutton', { name: 'Context window percentage' }); - for (const value of ['', '0', '9', '91', '12.5']) { - fireEvent.change(percent, { target: { value } }); - expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); - expect(screen.getByText('Use a whole-number percentage from 10 to 90, or choose Automatic.')).toBeDefined(); - } - fireEvent.change(percent, { target: { value: '65' } }); - expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', false); - act(() => { f.root.active_turns = { root: 'turn' } as unknown as RootSnapshot['active_turns']; }); - fireEvent.change(percent, { target: { value: '66' } }); + await screen.findByRole('combobox', { name: 'Compact at' }); expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); expect(screen.getByRole('button', { name: 'Compact now' })).toHaveProperty('disabled', true); expect(f.client.configuration.update).not.toHaveBeenCalled(); @@ -695,34 +679,33 @@ describe('compaction defaults', () => { }); }); -it('saves only the inspector threshold edit, including Automatic reset', async () => { +it('saves only the inspector threshold edit, including explicit 50%', async () => { const f = fixture(); f.client.configuration.get.mockResolvedValue({ revision: '1', compact_model: 'original', compact_provider: 'provider', compact_percent: 60 }); f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · 60%'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: '65' } }); + await screen.findByRole('combobox', { name: 'Compact at' }); + fireEvent.click(screen.getByRole('combobox', { name: 'Compact at' })); + await userEvent.click(await screen.findByRole('option', { name: '70%', exact: true })); fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); await waitFor(() => expect(f.run).toHaveBeenCalledTimes(1)); - expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_percent: 65 }); + expect(f.client.configuration.update).toHaveBeenCalledWith({ revision: '1', compact_percent: 70 }); await waitFor(() => expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', false)); - fireEvent.click(screen.getByRole('combobox', { name: 'Compaction timing' })); - await userEvent.click(await screen.findByRole('option', { name: 'Automatic · 50%', exact: true })); + fireEvent.click(screen.getByRole('combobox', { name: 'Compact at' })); + await userEvent.click(await screen.findByRole('option', { name: '50%', exact: true })); fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); await waitFor(() => expect(f.run).toHaveBeenCalledTimes(2)); - expect(f.client.configuration.update).toHaveBeenLastCalledWith({ revision: '1', compact_percent: 0 }); + expect(f.client.configuration.update).toHaveBeenLastCalledWith({ revision: '1', compact_percent: 50 }); }); it('disables inspector defaults while a save is pending', async () => { const f = fixture(); f.client.configuration.update.mockImplementationOnce(() => new Promise(() => {})); f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · original · provider'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); + await screen.findByRole('button', { name: 'Summary model' }); fireEvent.click(screen.getByRole('button', { name: 'Apply compaction defaults' })); await waitFor(() => expect(f.client.configuration.update).toHaveBeenCalled()); - expect(screen.getByRole('combobox', { name: 'Summary model mode' })).toHaveProperty('disabled', true); - expect(screen.getByRole('button', { name: 'Custom summary model' })).toHaveProperty('disabled', true); + expect(screen.getByRole('combobox', { name: 'Compact at' })).toHaveProperty('disabled', true); + expect(screen.getByRole('button', { name: 'Summary model' })).toHaveProperty('disabled', true); expect(screen.getByRole('button', { name: 'Refresh compaction defaults' })).toHaveProperty('disabled', true); expect(f.run).not.toHaveBeenCalled(); }); @@ -730,15 +713,14 @@ it('disables inspector defaults while a save is pending', async () => { it('preserves a compaction draft when disconnect cleanup removes configuration data', async () => { const f = fixture(); const view = f.render(<Compaction {...f.props} />); - await screen.findByText('Custom · original · provider'); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + await screen.findByRole('button', { name: 'Summary model' }); + fireEvent.click(screen.getByRole('button', { name: 'Summary model' })); fireEvent.click(await screen.findByRole('option', { name: 'my-model · provider' })); act(() => { f.queries.removeQueries({ queryKey: ['inspector-compaction-config', 'runtime'] }); }); view.rerender(f.wrapper(<Compaction {...f.props} connected={false} />)); - expect(screen.getByText('Custom · my-model · provider')).toBeDefined(); + expect(screen.getByRole('button', { name: 'Summary model' })).toBeDefined(); expect(screen.getByRole('button', { name: 'Apply compaction defaults' })).toHaveProperty('disabled', true); expect(f.client.configuration.update).not.toHaveBeenCalled(); }); diff --git a/packages/app/test/model-selection.test.tsx b/packages/app/test/model-selection.test.tsx index 1b49c1a0d..13d686a62 100644 --- a/packages/app/test/model-selection.test.tsx +++ b/packages/app/test/model-selection.test.tsx @@ -65,6 +65,7 @@ it('switches the provider when the selected model name is unchanged', async () = fireEvent.click(await screen.findByRole('button', { name: 'Model', exact: true })); const current = await screen.findByRole('option', { name: 'gpt-5.5 · openrouter' }); expect(current.getAttribute('aria-selected')).toBe('true'); + expect(screen.queryByRole('option', { name: 'Conversation Model' })).toBeNull(); fireEvent.change(screen.getByRole('textbox', { name: 'Search models' }), { target: { value: 'openai-codex' } }); expect(screen.queryByRole('option', { name: 'gpt-5.5 · openrouter' })).toBeNull(); const subscription = screen.getByRole('option', { name: 'gpt-5.5 · openai-codex' }); diff --git a/packages/app/test/settings-configuration.test.tsx b/packages/app/test/settings-configuration.test.tsx index 4e989172f..173babb1c 100644 --- a/packages/app/test/settings-configuration.test.tsx +++ b/packages/app/test/settings-configuration.test.tsx @@ -264,99 +264,112 @@ it('disables permission changes while disconnected or saving', async () => { expect(screen.getByRole('button', { name: 'Default permission level' })).toHaveProperty('disabled', true); }); -async function chooseCompactionMode(label: string, option: string) { - fireEvent.click(screen.getByRole('combobox', { name: label, exact: true })); - await userEvent.click(await screen.findByRole('option', { name: option, exact: true })); + +async function chooseThreshold(percent: number) { + fireEvent.click(await screen.findByRole('combobox', { name: 'Compact at', exact: true })); + await userEvent.click(await screen.findByRole('option', { name: percent + '%', exact: true })); +} +async function chooseSummary(name: string) { + fireEvent.click(await screen.findByRole('button', { name: 'Summary model', exact: true })); + fireEvent.click(await screen.findByRole('option', { name, exact: true })); } -it('keeps automatic compaction simple and only loads connected custom routes on demand', async () => { +it('shows two compaction controls and only loads connected model routes on demand', async () => { const f = fixture(); f.changeServer({ ...initial, compact_model: '', compact_provider: '', compact_percent: 0 }); f.render('execution'); const group = await screen.findByRole('region', { name: 'Context compaction' }); - expect(within(group).getByText('Automatic · conversation model and provider')).toBeDefined(); - expect(within(group).getByText('Automatic · 50%')).toBeDefined(); - expect(within(group).getByText('Older active context is summarized. Full conversation history remains available.')).toBeDefined(); - expect(within(group).queryByRole('combobox')).toBeNull(); + expect(within(group).getByRole('button', { name: 'Summary model' }).textContent).toBe('Conversation Model'); + expect(within(group).getByRole('combobox', { name: 'Compact at' }).textContent).toBe('50%'); + expect(within(group).queryByText(/Advanced/)).toBeNull(); + expect(within(group).queryByText('Summarize older context while keeping the full conversation history.')).toBeNull(); + expect(within(group).queryByRole('spinbutton')).toBeNull(); + expect(within(group).getByText(/requires an up-to-date execution host/)).toBeDefined(); expect(f.client.providers.catalogs).not.toHaveBeenCalled(); - fireEvent.click(within(group).getByRole('button', { name: 'Advanced compaction settings' })); - expect(f.client.providers.catalogs).not.toHaveBeenCalled(); - await chooseCompactionMode('Summary model mode', 'Custom'); - fireEvent.click(screen.getByRole('button', { name: 'Custom summary model' })); + fireEvent.click(screen.getByRole('button', { name: 'Summary model' })); expect(await screen.findByRole('option', { name: 'model-a · subscription' })).toBeDefined(); expect(screen.queryByRole('option', { name: 'offline-model · offline' })).toBeNull(); expect(screen.queryByRole('option', { name: 'unknown-model · unknown' })).toBeNull(); fireEvent.click(screen.getByRole('option', { name: 'model-a · subscription' })); + expect(f.update).not.toHaveBeenCalled(); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: 'model-a', compact_provider: 'subscription' }); - expect(screen.getByText('Custom · model-a · subscription')).toBeDefined(); + expect(screen.getByRole('button', { name: 'Summary model' }).title).toBe('model-a · subscription'); + expect(screen.getByRole('button', { name: 'Summary model' }).textContent).toContain('subscription'); expect(screen.queryByRole('textbox', { name: /provider/i })).toBeNull(); + await chooseSummary('Conversation Model'); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await waitFor(() => expect(f.update).toHaveBeenCalledTimes(2)); + expect(f.update.mock.calls[1]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); }); -it('retains a saved deepseek override until Automatic explicitly clears both fields', async () => { - const f = fixture(); f.changeServer({ ...initial, compact_model: 'deepseek-v3.2', compact_provider: 'inference' }); - f.render('execution'); - expect(await screen.findByText('Custom · deepseek-v3.2 · inference')).toBeDefined(); +it('offers exactly nine new percentage choices', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); f.render('execution'); + fireEvent.click(await screen.findByRole('combobox', { name: 'Compact at' })); + const options = await screen.findAllByRole('option'); + expect(options.map(option => option.textContent)).toEqual(['10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%']); +}); + +it.each([10, 20, 30, 40, 50, 60, 70, 80, 90])('saves the explicit %i%% choice', async percent => { + const f = fixture(); f.render('execution'); + await chooseThreshold(percent); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await screen.findByText('Host defaults saved.'); + expect(f.update.mock.calls[0]![0].compact_percent).toBe(percent); + expect(screen.getByRole('combobox', { name: 'Compact at' }).textContent).toBe(percent + '%'); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_model'); +}); + +it.each([0, 50, 65, 5, 95])('preserves raw %i and an unavailable route during unrelated saves', async raw => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: raw }); f.render('execution'); + const control = await screen.findByRole('combobox', { name: 'Compact at' }); + const effective = raw === 0 ? 50 : Math.max(10, Math.min(90, raw)); + expect(control.textContent).toContain(effective + '%'); + if (![0, 50].includes(raw)) expect(control.textContent).toContain('saved value'); + if (raw === 5 || raw === 95) expect(screen.getByText('Saved value: ' + raw + '%. The effective threshold is ' + effective + '%; kept until you change it.')).toBeDefined(); expect(screen.getByRole('button', { name: 'Save host defaults' })).toHaveProperty('disabled', true); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - expect(screen.getByRole('combobox', { name: 'Summary model mode' }).textContent).toBe('Custom'); - await chooseCompactionMode('Summary model mode', 'Automatic'); + fireEvent.change(screen.getByRole('spinbutton', { name: 'Retry limit' }), { target: { value: '4' } }); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); - expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_percent'); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_model'); + expect((f.queries.getQueryData(['runtime-configuration', 'host-a']) as RuntimeConfiguration).compact_percent).toBe(raw); }); -it.each(['', '0', '9', '91', '10.5'])('rejects custom threshold %j without writing', async threshold => { - const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); - const view = f.render('execution'); - fireEvent.click(await screen.findByRole('button', { name: 'Advanced compaction settings' })); - await chooseCompactionMode('Compaction timing', 'Custom'); - fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: threshold } }); - fireEvent.submit(view.container.querySelector('form')!); - await waitFor(() => expect(view.container.querySelector('[data-error-type="validation"]')).not.toBeNull()); +it('does not dirty the form when returning to an unset 50% default', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); f.render('execution'); + await chooseThreshold(60); await chooseThreshold(50); + expect(screen.getByRole('button', { name: 'Save host defaults' })).toHaveProperty('disabled', true); expect(f.update).not.toHaveBeenCalled(); - expect(screen.getByRole('spinbutton', { name: 'Context window percentage' }).getAttribute('aria-invalid')).toBe('true'); }); -it.each([10, 90])('saves custom threshold %i and can reset to Automatic', async threshold => { - const f = fixture(); f.changeServer({ ...initial, compact_percent: 0 }); - f.render('execution'); - fireEvent.click(await screen.findByRole('button', { name: 'Advanced compaction settings' })); - await chooseCompactionMode('Compaction timing', 'Custom'); - fireEvent.change(screen.getByRole('spinbutton', { name: 'Context window percentage' }), { target: { value: String(threshold) } }); +it('replaces a clamped legacy threshold when its effective value is explicitly selected', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_percent: 95 }); f.render('execution'); + await chooseThreshold(90); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); - expect(f.update.mock.calls[0]![0].compact_percent).toBe(threshold); - await chooseCompactionMode('Compaction timing', 'Automatic · 50%'); - fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); - await waitFor(() => expect(f.update).toHaveBeenCalledTimes(2)); - expect(f.update.mock.calls[1]![0].compact_percent).toBe(0); + expect(f.update.mock.calls[0]![0].compact_percent).toBe(90); }); -it.each([[5, 10], [95, 90], [-2, 10]])('shows the effective legacy threshold for %i without rewriting it', async (raw, effective) => { - const f = fixture(); f.changeServer({ ...initial, compact_percent: raw }); - const view = f.render('execution'); - expect(await screen.findByText('Custom · ' + effective + '%')).toBeDefined(); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - expect(view.container.querySelector('form')).toHaveProperty('noValidate', true); - expect((screen.getByRole('spinbutton', { name: 'Context window percentage' }) as HTMLInputElement).checkValidity()).toBe(false); - expect(screen.getByText('Saved value: ' + raw + '%. The effective threshold is ' + effective + '%; saving other settings keeps the saved value.')).toBeDefined(); +it('preserves a provider-only legacy value until Conversation Model is explicitly selected', async () => { + const f = fixture(); f.changeServer({ ...initial, compact_model: '', compact_provider: 'inference', compact_percent: 0 }); f.render('execution'); + expect((await screen.findByRole('button', { name: 'Summary model' })).textContent).toBe('Conversation Model'); fireEvent.change(screen.getByRole('spinbutton', { name: 'Retry limit' }), { target: { value: '4' } }); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); - expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_percent'); - expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_model'); - expect((f.queries.getQueryData(['runtime-configuration', 'host-a']) as RuntimeConfiguration).compact_percent).toBe(raw); + expect(f.update.mock.calls[0]![0]).not.toHaveProperty('compact_provider'); + await chooseSummary('Conversation Model'); + fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); + await waitFor(() => expect(f.update).toHaveBeenCalledTimes(2)); + expect(f.update.mock.calls[1]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); }); -it('ignores a provider-only legacy override until an explicit Automatic reset', async () => { - const f = fixture(); f.changeServer({ ...initial, compact_model: '', compact_provider: 'inference', compact_percent: 0 }); - f.render('execution'); - expect(await screen.findByText('Automatic · conversation model and provider')).toBeDefined(); - fireEvent.click(screen.getByRole('button', { name: 'Advanced compaction settings' })); - await chooseCompactionMode('Summary model mode', 'Custom'); - await chooseCompactionMode('Summary model mode', 'Automatic'); +it('keeps Conversation Model available during a failed catalog fetch and an unmatched search', async () => { + const f = fixture(); vi.mocked(f.client.providers.catalogs).mockRejectedValue(new Error('Offline')); f.render('execution'); + fireEvent.click(await screen.findByRole('button', { name: 'Summary model' })); + await screen.findByText('Could not load models'); + fireEvent.change(screen.getByRole('textbox', { name: 'Search models' }), { target: { value: 'nonexistent' } }); + fireEvent.click(screen.getByRole('option', { name: 'Conversation Model' })); fireEvent.click(screen.getByRole('button', { name: 'Save host defaults' })); await screen.findByText('Host defaults saved.'); expect(f.update.mock.calls[0]![0]).toMatchObject({ compact_model: '', compact_provider: '' }); diff --git a/packages/protocol/README.md b/packages/protocol/README.md index 7f7c39094..d61a55760 100644 --- a/packages/protocol/README.md +++ b/packages/protocol/README.md @@ -1,9 +1,21 @@ -# WHIP protocol v5 contracts +# WHIP protocol contracts This package contains generated TypeScript declarations, Draft-07 JSON Schema, and Ajv validators for the Go protocol registry. It has no UI or transport state. -Use Node 24 and `npm ci`; regenerate with `npm run generate` and verify types, -Go-produced interoperability fixtures, and drift with `npm run check`. +Use Node 24, the Go toolchain in `go.mod`, and Task. From the repository root: + +```sh +npm ci +task generate +npm run check +``` + +`task generate` creates the schemas, manifest and Go-marshaled interoperability +fixtures in `schema/`, then JavaScript validators and TypeScript declarations in +`generated/`, and finally builds the SDK. Both output directories are ignored by +Git. `npm run check` verifies freshness, types and interoperability without +regenerating protocol output. To check freshness alone, run +`npm run check:drift -w @whip/protocol`. ```ts import { assertValid, type SubscribeParams } from '@whip/protocol'; @@ -21,15 +33,19 @@ and existing permission requirements for each RPC and runtime operation. Runtime operations travel inside `command.submit` or `query`; the latter never journals work. A command's RPC request ID is separate from its durable command ID. Client IDs provide retry namespaces and are not authenticated identities. -The wire major is 5. Required archive metadata and catalog cursor status are -incompatible with earlier majors; clients and daemons reject them at initialization. +Clients and daemons must agree on the wire major; incompatible clients are +rejected at initialization. Do not coerce decimal strings into JavaScript numbers. Binary fields use base64; JSON payloads remain JSON. Permission decisions use ordinary unsigned payloads. Never persist provider credentials or terminal input in a client retry queue. A dropped connection does not cancel an accepted command. -Generated files are checked in for consumers. Edit `internal/protocol` rather -than these files, then regenerate. The daemon validates against the same Go +Edit the definitions in `internal/protocol` or the generators rather than their +output. Rerun `task generate` after pulling, switching branches, or editing those +sources; rerun `npm ci` first when dependencies change. Ordinary builds use the +prepared files, and checks reject missing or stale output instead of rewriting it. +Package archives include the generated JavaScript and declarations, so consumers +do not need Go or generation tools. The daemon validates against the same Go schema builder before admitting operations. Snapshot and command result payloads must also be validated against the result type named in the registry. diff --git a/packages/protocol/generated/index.d.ts b/packages/protocol/generated/index.d.ts deleted file mode 100644 index 22db68dd2..000000000 --- a/packages/protocol/generated/index.d.ts +++ /dev/null @@ -1,4526 +0,0 @@ -// Generated from Go wire types. Run npm run generate. -export interface Accepted { - accepted: boolean; -} - -export interface AgentCancelParams { - id: string; - turn_id: string; -} - -export interface AgentInputParams { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - id: string; - text: string; - delivery?: string; - parts?: - | null - | { - type: string; - text?: string; - image_url?: null | { - url: string; - }; - w?: number; - h?: number; - }[]; - attachments?: - | null - | { - kind: "image" | "text"; - content: { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - name?: string; - }[]; -} - -export type AgentListResult = - | null - | { - execution_engine: string; - last_turn?: null | { - turn_id?: string; - status: string; - started_at?: string; - finished_at?: string; - event_seq: string; - error?: string; - error_truncated?: boolean; - error_details?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - model_calls?: number; - compactions?: number; - last_activity_at?: string; - }; - id: string; - root_id: string; - parent_id: string; - name: string; - model: string; - provider: string; - effort: string; - cwd: string; - report: string; - status: string; - pending_mail: number; - lifecycle_phase: string; - blocking_reason: string; - terminal_cause: string; - allowed_controls: null | string[]; - }[]; - -export interface AgentSubmitResult { - agent_id: string; - inbox_seq: string; - kind?: string; - status: string; -} - -export interface AgentTranscriptResult { - accounting?: { - root_id: string; - agent_id: string; - scope: string; - revision: string; - reported_cost_micros: string; - estimated_cost_micros: string; - reported_cost_calls: string; - estimated_cost_calls: string; - unknown_cost_calls: string; - reported_calls: string; - estimated_calls: string; - pending_calls: string; - }; - cursor: string; - agent: { - execution_engine: string; - last_turn?: null | { - turn_id?: string; - status: string; - started_at?: string; - finished_at?: string; - event_seq: string; - error?: string; - error_truncated?: boolean; - error_details?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - model_calls?: number; - compactions?: number; - last_activity_at?: string; - }; - id: string; - root_id: string; - parent_id: string; - name: string; - model: string; - provider: string; - effort: string; - cwd: string; - report: string; - status: string; - pending_mail: number; - lifecycle_phase: string; - blocking_reason: string; - terminal_cause: string; - allowed_controls: null | string[]; - }; - page: { - history_revision: string; - through_seq: number; - next_seq: number; - has_more: boolean; - messages: - | null - | { - presentation?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - context_part_index: number; - screenshot_part_index?: null | number; - }; - version: number; - turn_id?: string; - parts?: - | null - | { - id: string; - kind: string; - start?: number; - end?: number; - text?: string; - tool_name?: string; - status?: string; - call_id?: string; - hosts?: - | null - | { - invocation_id: string; - name: string; - summary?: string; - status: string; - duration?: string; - error?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - }[]; - omitted?: number; - }[]; - omitted?: number; - }; - role?: string; - authored?: boolean; - sent_at?: null | string; - seq: number; - message?: null | { - presentation?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - context_part_index: number; - screenshot_part_index?: null | number; - }; - version: number; - turn_id?: string; - parts?: - | null - | { - id: string; - kind: string; - start?: number; - end?: number; - text?: string; - tool_name?: string; - status?: string; - call_id?: string; - hosts?: - | null - | { - invocation_id: string; - name: string; - summary?: string; - status: string; - duration?: string; - error?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - }[]; - omitted?: number; - }[]; - omitted?: number; - }; - role: string; - content: - | string - | { - type: string; - text?: string; - image_url?: null | { - url: string; - }; - w?: number; - h?: number; - }[]; - tool_calls?: - | null - | { - id: string; - type: string; - function: { - name: string; - arguments: string; - }; - duration_ms?: number; - exit_code?: number; - }[]; - tool_call_id?: string; - name?: string; - authored?: boolean; - sent_at?: null | string; - usage?: null | { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; - model?: string; - rewound_from?: string; - call_id?: string; - }; - body?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - }; - presentation?: - | null - | { - seq: string; - kind: string; - payload: unknown; - }[]; - inbox?: - | null - | { - delivery_seq?: string; - origin?: string; - command_client_id?: string; - command_id?: string; - steer_turn_id?: string; - preview?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - text: string; - truncated?: boolean; - attachments?: - | null - | { - kind: string; - name?: string; - content: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - attachment_count?: number; - }; - root_id: string; - agent_id: string; - seq: string; - kind: string; - status: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; -} - -export interface ArchiveParams { - archived: boolean; -} - -export interface ArchiveResult { - archived: boolean; -} - -export interface BoundedTranscriptPage { - history_revision: string; - through_seq: number; - next_seq: number; - has_more: boolean; - messages: - | null - | { - presentation?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - context_part_index: number; - screenshot_part_index?: null | number; - }; - version: number; - turn_id?: string; - parts?: - | null - | { - id: string; - kind: string; - start?: number; - end?: number; - text?: string; - tool_name?: string; - status?: string; - call_id?: string; - hosts?: - | null - | { - invocation_id: string; - name: string; - summary?: string; - status: string; - duration?: string; - error?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - }[]; - omitted?: number; - }[]; - omitted?: number; - }; - role?: string; - authored?: boolean; - sent_at?: null | string; - seq: number; - message?: null | { - presentation?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - context_part_index: number; - screenshot_part_index?: null | number; - }; - version: number; - turn_id?: string; - parts?: - | null - | { - id: string; - kind: string; - start?: number; - end?: number; - text?: string; - tool_name?: string; - status?: string; - call_id?: string; - hosts?: - | null - | { - invocation_id: string; - name: string; - summary?: string; - status: string; - duration?: string; - error?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - }[]; - omitted?: number; - }[]; - omitted?: number; - }; - role: string; - content: - | string - | { - type: string; - text?: string; - image_url?: null | { - url: string; - }; - w?: number; - h?: number; - }[]; - tool_calls?: - | null - | { - id: string; - type: string; - function: { - name: string; - arguments: string; - }; - duration_ms?: number; - exit_code?: number; - }[]; - tool_call_id?: string; - name?: string; - authored?: boolean; - sent_at?: null | string; - usage?: null | { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; - model?: string; - rewound_from?: string; - call_id?: string; - }; - body?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; -} - -export interface BrowserCommand { - command_id: string; - operation_id: string; - root_id: string; - agent_id: string; - provider_epoch: string; - scope: { - provider_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - profile_id: string; - attachment_id?: string; - attachment_generation?: string; - rights: null | string[]; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }; - expected_document?: string; - deadline_millis: string; - kind: string; - arguments: unknown; -} - -export interface BrowserCommandCancel { - command_id: string; - root_id: string; - provider_epoch: string; - attachment_generation: string; - reason: string; -} - -export interface BrowserCommandResultParams { - command_id: string; - root_id: string; - provider_epoch: string; - attachment_generation: string; - document_revision: string; - result?: unknown; - error?: null | { - kind: string; - message: string; - }; - screenshot?: null | { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; -} - -export interface BrowserDriverParams { - driver: string; -} - -export interface BrowserInventoryRequest { - request_id: string; - root_id: string; - agent_id: string; - provider_id: string; - provider_epoch: string; - tabs: - | null - | { - tab_id: string; - tab_generation: string; - }[]; -} - -export interface BrowserInventoryResultParams { - request_id: string; - root_id: string; - provider_epoch: string; - tabs: - | null - | { - tab_id: string; - tab_generation: string; - document_revision: string; - url: string; - title: string; - state: string; - requestable: boolean; - attachment_id?: string; - }[]; - error?: null | { - kind: string; - message: string; - }; -} - -export interface BrowserProviderBindParams { - availability?: boolean; - root_id: string; - version: number; - desktop_id: string; - window_id: string; - offer_revision: string; - create_profile_id: string; - expected_provider_epoch?: string; - offered_tabs: - | null - | { - tab_id: string; - tab_generation: string; - profile_id: string; - document_revision?: string; - url?: string; - title?: string; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }[]; - offered_preview_hosts: - | null - | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }[]; -} - -export interface BrowserProviderBindResult { - version: number; - provider_id: string; - provider_epoch: string; -} - -export interface BrowserProviderEventParams { - root_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - attachment_id: string; - attachment_generation: string; - sequence: string; - operation_id?: string; - document_revision: string; - kind: string; - method?: string; - params?: unknown; - url?: string; - title?: string; -} - -export interface BrowserProviderRevoked { - root_id: string; - provider_id: string; - provider_epoch: string; - reason: string; -} - -export interface BrowserProviderUnbindParams { - root_id: string; - provider_epoch: string; -} - -export interface BrowserStatusResult { - enabled: boolean; - driver?: string; -} - -export interface BudgetCapParams { - id: string; - kind: string; - limit: string; -} - -export interface BudgetState { - kind: string; - limit: string | null; - used: string; - reserved: string; - remaining: string | null; - uncertain: string; - incomplete: boolean; -} - -export interface CancelParams { - turn_id?: string; - target_command_id?: string; -} - -export interface CapabilityRecord { - id: string; - root_id: string; - agent_id: string; - issuer_agent_id: string; - operations: null | string[]; - scopes: null | string[]; - file_scope?: string; - file_issuer_id?: string; - file_issuer_generation?: string; - mcp: - | null - | { - server: string; - tool: string; - definition: string; - }[]; - mcp_all: boolean; - browser?: null | { - provider_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - profile_id: string; - attachment_id?: string; - attachment_generation?: string; - rights: null | string[]; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }; - browser_issuer_id?: string; - browser_issuer_generation?: number; - browser_delegation_only?: boolean; - generation: string; - status: string; - expires_at: string; - created_at: string; - updated_at: string; -} - -export interface CatalogResult { - themes: - | null - | { - id: string; - name: string; - dark: boolean; - source: string; - }[]; - errors: - | null - | { - file: string; - message: string; - }[]; - truncated: boolean; -} - -export interface CatalogRevision { - revision: string; -} - -export interface CheckpointParams { - reason?: string; -} - -export interface ClearHistoryParams { - expected_revision?: string | null; -} - -export interface CommandParams { - command_id: string; - scope: string; - root_id?: string; - operation: string; - payload?: unknown; -} - -export interface CommandResult { - content?: null | { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - operation: string; - result?: unknown; - failure?: null | { - data?: null | { - kind: string; - }; - code: number; - message: string; - }; - command_id: string; - ingress_seq: string; - status: string; -} - -export interface CommandStatusParams { - command_id: string; -} - -export type CompactionListResult = - | null - | { - seq: number; - cutoff: number; - summary: string; - }[]; - -export interface CompactionParams { - model?: string; - provider?: string; -} - -export interface CompactionResult { - cutoff: number; - model?: string; - usage: { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; -} - -export interface CompactionRetryResult { - undone: boolean; - sequence?: number; -} - -export interface CompactionSettingsResult { - model?: string; - provider?: string; - builtin_default: boolean; -} - -export interface CompletionParams { - root_id: string; - agent_id?: string; - kind: string; - prefix: string; - limit: number; -} - -export interface CompletionResult { - warnings?: null | string[]; - candidates: - | null - | { - text: string; - description: string; - }[]; - truncated: boolean; -} - -export interface ComputerAppParams { - app: string; -} - -export interface ComputerStatusResult { - enabled: boolean; - default_deny: boolean; - allowed: null | string[]; - denied: null | string[]; - session_allowed: null | string[]; - session_denied: null | string[]; -} - -export interface ConfigurationUpdate { - default_execution_engine?: null | string; - disabled_providers?: null | string[]; - remote_hosts?: - | null - | { - id: string; - name: string; - url: string; - runtime_id: string; - connect_on_launch: boolean; - }[]; - import_claude?: null | boolean; - import_codex?: null | boolean; - brand_icons?: null | boolean; - revision: string; - default_model?: null | string; - default_provider?: null | string; - default_effort?: null | string; - default_permission_mode?: null | string; - compact_model?: null | string; - compact_provider?: null | string; - compact_percent?: null | number; - goal_max_rounds?: null | number; - max_retries?: null | number; -} - -export interface ContentEventPayload { - part_id?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - accounting?: null | { - root_id: string; - agent_id: string; - scope: string; - revision: string; - reported_cost_micros: string; - estimated_cost_micros: string; - reported_cost_calls: string; - estimated_cost_calls: string; - unknown_cost_calls: string; - reported_calls: string; - estimated_calls: string; - pending_calls: string; - }; - usage?: null | { - used: number; - size: number; - usage: { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; - }; - agent_id?: string; - turn_id?: string; - invocation_id?: string; - operation_id?: string; - host_status?: string; - id?: string; - name?: string; - text?: string; - args?: string; - result?: string; - content: { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - truncated: true; -} - -export interface ContentHandle { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; -} - -export interface ContentReadParams { - root_id: string; - agent_id?: string; - reference_id: string; - offset: string; - limit: number; -} - -export interface ContentReadResult { - data: string | null; - content: { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; -} - -export interface ContextAuditResult { - working_directory: string; - rows: - | null - | { - label: string; - bytes?: number; - note?: string; - }[]; -} - -export interface CreateSessionParams { - execution_engine?: string; - definition?: string; - kind: string; - cwd: string; - model: string; - provider: string; - effort?: string; - permission_mode?: string; -} - -export interface DefinitionList { - items: - | null - | { - id: string; - revision: string; - built_in: boolean; - registered_by: string; - created_at: string; - }[]; -} - -export interface DefinitionParams { - id: string; - revision?: string; -} - -export interface DefinitionRecord { - definition: { - id: string; - instructions: { - persona: string; - rules: string; - project_files: null | string[]; - skill_discovery: boolean; - standing_instructions: boolean; - }; - modules: null | string[]; - capabilities: null | string[]; - model: { - model: string; - provider: string; - effort: string; - }; - compaction: { - model: string; - provider: string; - threshold: number; - }; - mcp: { - servers: null | string[]; - }; - tools: - | null - | { - name: string; - description: string; - input_schema: unknown; - output_schema: unknown; - timeout_millis: number; - }[]; - output: unknown; - children: { - [k: string]: { - instructions: null | { - persona: string; - rules: string; - project_files: null | string[]; - skill_discovery: boolean; - standing_instructions: boolean; - }; - modules: null | string[]; - capabilities: null | string[]; - tools: null | string[]; - model: { - model: string; - provider: string; - effort: string; - }; - budgets: { - [k: string]: number; - }; - report: string; - output: unknown; - }; - }; - surface: { - auto_title: boolean; - goal_loop: boolean; - }; - hooks: null | { - before_tool: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - before_spawn: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - turn_start: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - }; - }; - revision: string; - built_in: boolean; - registered_by: string; - created_at: string; -} - -export interface DefinitionRegisterParams { - definition: { - id: string; - instructions: { - persona: string; - rules: string; - project_files: null | string[]; - skill_discovery: boolean; - standing_instructions: boolean; - }; - modules: null | string[]; - capabilities: null | string[]; - model: { - model: string; - provider: string; - effort: string; - }; - compaction: { - model: string; - provider: string; - threshold: number; - }; - mcp: { - servers: null | string[]; - }; - tools: - | null - | { - name: string; - description: string; - input_schema: unknown; - output_schema: unknown; - timeout_millis: number; - }[]; - output: unknown; - children: { - [k: string]: { - instructions: null | { - persona: string; - rules: string; - project_files: null | string[]; - skill_discovery: boolean; - standing_instructions: boolean; - }; - modules: null | string[]; - capabilities: null | string[]; - tools: null | string[]; - model: { - model: string; - provider: string; - effort: string; - }; - budgets: { - [k: string]: number; - }; - report: string; - output: unknown; - }; - }; - surface: { - auto_title: boolean; - goal_loop: boolean; - }; - hooks: null | { - before_tool: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - before_spawn: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - turn_start: null | { - operations: null | string[]; - optional: boolean; - timeout_millis: number; - }; - }; - }; -} - -export interface DefinitionRegisterResult { - id: string; - revision: string; - created: boolean; -} - -export interface EffortParams { - effort: string; - persist_default: boolean; -} - -export interface EffortResult { - effort: string; -} - -export interface Empty {} - -export interface EmptyParams {} - -export interface EventNotification { - event: { - subscription_id?: string; - root_id: string; - seq: string; - kind: string; - payload?: unknown; - }; -} - -export interface ExecutorBindParams { - definition: string; - revision: string; - tools: null | string[]; - hooks?: null | string[]; -} - -export interface ExecutorBindResult { - generation: string; - tools: null | string[]; - hooks?: null | string[]; -} - -export interface ExecutorPendingParams { - definition: string; - revision: string; - generation: string; -} - -export interface ExecutorPendingResult { - invocations: - | null - | { - invocation_id: string; - definition: string; - revision: string; - generation: string; - root_id: string; - agent_id: string; - turn_id: string; - tool: string; - input: unknown; - deadline_millis: string; - }[]; - hooks?: - | null - | { - invocation_id: string; - definition: string; - revision: string; - generation: string; - root_id: string; - agent_id: string; - turn_id: string; - hook: string; - operation?: string; - arguments?: unknown; - spawn?: null | { - request: { - prompt: string; - name: string; - definition: string; - capabilities: null | string[]; - tools: null | string[]; - budgets: { - [k: string]: number; - }; - report: string; - model: string; - provider: string; - effort: string; - mcp_tools?: unknown; - browser_attachments?: null | string[]; - }; - resolved: { - browser_attachments?: null | string[]; - definition: string; - modules: null | string[]; - capabilities: null | string[]; - tools: null | string[]; - budgets: { - [k: string]: number; - }; - report: string; - }; - }; - input?: string; - permission_mode: string; - deadline_millis: string; - }[]; -} - -export interface ForkParams { - expected_revision: string | null; - title?: string; - cut?: number; -} - -export interface GatewayStatus { - state: string; - endpoint?: string; - error?: string; -} - -export interface GoalContextParams { - window?: number; -} - -export interface GoalResult { - goal: string; -} - -export interface HistoryPageParams { - root_id: string; - agent_id: string; - after_seq?: number; - before_seq?: number; - through_seq: number; - revision?: string | null; - limit: number; - max_bytes: number; - recent?: boolean; -} - -export interface HookInvokeParams { - invocation_id: string; - definition: string; - revision: string; - generation: string; - root_id: string; - agent_id: string; - turn_id: string; - hook: string; - operation?: string; - arguments?: unknown; - spawn?: null | { - request: { - prompt: string; - name: string; - definition: string; - capabilities: null | string[]; - tools: null | string[]; - budgets: { - [k: string]: number; - }; - report: string; - model: string; - provider: string; - effort: string; - mcp_tools?: unknown; - browser_attachments?: null | string[]; - }; - resolved: { - browser_attachments?: null | string[]; - definition: string; - modules: null | string[]; - capabilities: null | string[]; - tools: null | string[]; - budgets: { - [k: string]: number; - }; - report: string; - }; - }; - input?: string; - permission_mode: string; - deadline_millis: string; -} - -export interface HookResultParams { - invocation_id: string; - generation: string; - decision?: string; - reason?: string; - arguments?: unknown; - spawn?: null | { - prompt: string; - name: string; - definition: string; - capabilities: null | string[]; - tools: null | string[]; - budgets: { - [k: string]: number; - }; - report: string; - model: string; - provider: string; - effort: string; - mcp_tools?: unknown; - browser_attachments?: null | string[]; - }; - context?: string; - error?: string; -} - -export interface HostAttentionParams { - after_id?: string; - limit: number; - max_bytes: number; -} - -export interface HostAttentionResult { - items: - | null - | { - root_id: string; - title: string; - active_agents: string; - pending_permissions: string; - questions: - | null - | { - turn_id?: string; - root_id?: string; - agent_id?: string; - sender_agent_id?: string; - inbox_seq?: string; - inbox_kind?: string; - delivery?: string; - message_id?: string; - phase?: string; - status?: string; - terminal_cause?: string; - command_client_id?: string; - command_id?: string; - operation_id?: string; - trace_id?: string; - schedule_id?: number; - slot?: string; - error?: string; - model_call?: null | { - id: string; - logical_id: string; - number: number; - purpose: string; - usage_source: string; - cost_source: string; - tokens: string; - cost_micros: string; - elapsed_millis: string; - exhausted: boolean; - }; - acknowledged_inbox?: string[]; - subscription_id?: string; - key?: string; - version?: string; - expected_version?: string; - restored?: null | string[]; - not_restored?: - | null - | { - name: string; - reason: string; - }[]; - attempt?: string; - budget_kind?: string; - amount?: string; - limit?: string; - used?: string; - reserved?: string; - capability_id?: string; - generation?: string; - permission_id?: string; - operation?: string; - canonical_path?: string; - request_digest?: string; - command?: string; - rule?: string; - rule_source?: string; - question_id?: string; - question?: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - questions?: - | null - | { - question: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - }[]; - answer?: null | string[]; - dismissed?: boolean; - answers?: - | null - | { - answer?: null | string[]; - dismissed?: boolean; - }[]; - }[]; - truncated: boolean; - }[]; - next_after_id?: string; - has_more: boolean; - truncated: boolean; -} - -export interface HostDirectoryParams { - path?: string; - after?: string; - prefix?: string; - show_hidden?: boolean; - limit: number; -} - -export interface HostDirectoryPickParams { - start?: string; -} - -export interface HostDirectoryPickResult { - path?: string; - cancelled: boolean; -} - -export interface HostDirectoryResult { - path: string; - parent: string; - entries: - | null - | { - name: string; - path: string; - }[]; - next_after?: string; - has_more: boolean; - truncated: boolean; -} - -export type HostSkillCompletionParams = { - scope?: string; - cwd?: string; - definition?: string; - permission_mode?: string; - prefix: string; - limit: number; -} & ( - | { - cwd: string; - scope?: ""; - [k: string]: unknown; - } - | { - cwd?: ""; - scope: "global"; - [k: string]: unknown; - } -); - -export interface HostThemeResolveParams { - name?: string; - json?: string; -} - -export interface IDParams { - id: string; -} - -export interface InboxControlResult { - agent_id: string; - inbox_seq: string; - status: string; -} - -export interface InboxRemoveParams { - id: string; - inbox_seq: string; -} - -export interface InboxSteerParams { - id: string; - inbox_seq: string; - turn_id: string; -} - -export interface InitializeParams { - protocol_major: number; - build_id: string; - client_kind: string; - client_id: string; - capabilities?: null | string[]; -} - -export interface InitializeResult { - execution_engines: - | null - | { - bridge_sha256?: string; - build?: string; - abi?: string; - profile?: string; - fidelity?: string; - guide_sha256?: string; - features?: null | string[]; - default_limits?: { - [k: string]: number; - }; - id: string; - language: string; - label: string; - }[]; - default_execution_engine: string; - operations: - | null - | { - name: string; - surface: string; - execution: string; - permission: string; - sensitive?: boolean; - }[]; - limits: { - frame_bytes: number; - connections: number; - in_flight_requests: number; - outbound_messages: number; - outbound_bytes: string; - root_subscriptions: number; - content_chunk_bytes: number; - upload_bytes: string; - }; - negotiated_capabilities: null | string[]; - protocol_minor: number; - runtime_id: string; - connection_id: string; - host_platform: string; - host_architecture: string; - network_endpoint?: string; - protocol_major: number; - build_id: string; - generation: string; - pid?: number; - started_at?: string; - capabilities: null | string[]; -} - -export type LSPListResult = - | null - | { - name: string; - root?: string; - state: string; - error?: string; - }[]; - -export interface LifecycleEvent { - turn_id?: string; - root_id?: string; - agent_id?: string; - sender_agent_id?: string; - inbox_seq?: string; - inbox_kind?: string; - delivery?: string; - message_id?: string; - phase?: string; - status?: string; - terminal_cause?: string; - command_client_id?: string; - command_id?: string; - operation_id?: string; - trace_id?: string; - schedule_id?: number; - slot?: string; - error?: string; - model_call?: null | { - id: string; - logical_id: string; - number: number; - purpose: string; - usage_source: string; - cost_source: string; - tokens: string; - cost_micros: string; - elapsed_millis: string; - exhausted: boolean; - }; - acknowledged_inbox?: string[]; - subscription_id?: string; - key?: string; - version?: string; - expected_version?: string; - restored?: null | string[]; - not_restored?: - | null - | { - name: string; - reason: string; - }[]; - attempt?: string; - budget_kind?: string; - amount?: string; - limit?: string; - used?: string; - reserved?: string; - capability_id?: string; - generation?: string; - permission_id?: string; - operation?: string; - canonical_path?: string; - request_digest?: string; - command?: string; - rule?: string; - rule_source?: string; - question_id?: string; - question?: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - questions?: - | null - | { - question: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - }[]; - answer?: null | string[]; - dismissed?: boolean; - answers?: - | null - | { - answer?: null | string[]; - dismissed?: boolean; - }[]; -} - -export interface ListParams { - limit?: number; -} - -export interface MCPAttachParams { - servers: { - [k: string]: { - command?: null | string[]; - env?: { - [k: string]: string; - }; - cwd?: string; - url?: string; - headers?: { - [k: string]: string; - }; - enabled?: null | boolean; - note?: string; - startup_timeout?: number; - tool_timeout?: number; - source?: string; - origin?: string; - }; - }; -} - -export interface MCPBrandIconsParams { - keys: null | string[]; -} - -export interface MCPBrandIconsResult { - icons: { - [k: string]: string; - }; -} - -export interface MCPImportApplyParams { - cwd?: string; - names: null | string[]; -} - -export interface MCPImportApplyResult { - imported: null | string[]; - skipped?: { - [k: string]: string; - }; -} - -export interface MCPImportCandidatesParams { - cwd?: string; -} - -export interface MCPImportCandidatesResult { - candidates: - | null - | { - name: string; - source: string; - state: string; - note?: string; - brand_hint?: string; - brand_key?: string; - }[]; - offered: boolean; - config_path: string; - errors?: { - [k: string]: string; - }; -} - -export interface MCPImportParams { - source: string; - enabled: boolean; -} - -export interface MCPImportStatusResult { - claude: boolean; - codex: boolean; - project: boolean; - opencode: boolean; -} - -export type MCPListResult = - | null - | { - name: string; - status: string; - note?: string; - error?: string; - tools?: number; - source?: string; - }[]; - -export interface MCPRefreshResult { - added: null | string[]; - existing: null | string[]; - changed: null | string[]; - servers: - | null - | { - name: string; - status: string; - note?: string; - error?: string; - tools?: number; - source?: string; - }[]; - blocked: - | null - | { - name: string; - status: string; - note?: string; - error?: string; - tools?: number; - source?: string; - }[]; - source_errors: - | null - | { - name: string; - status: string; - note?: string; - error?: string; - tools?: number; - source?: string; - }[]; -} - -export interface MCPServerParams { - name: string; -} - -export interface MailboxInspection { - id: string; - revision: string; - sender: string; - recipient: string; - kind: string; - delivery: string; - subject: string; - excerpt: string; - body: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - evidence_handle?: string; - status: string; - available_at: string; - created_at: string; - delivered_at: string; - delivered_turn_id?: string; - done_at: string; -} - -export interface MailboxPage { - revision: string; - items: - | null - | { - id: string; - revision: string; - sender: string; - recipient: string; - kind: string; - delivery: string; - subject: string; - excerpt: string; - body: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - evidence_handle?: string; - status: string; - available_at: string; - created_at: string; - delivered_at: string; - delivered_turn_id?: string; - done_at: string; - }[]; - next_cursor?: null | { - root_id: string; - agent_id: string; - status: string; - revision: string; - offset: string; - }; - has_more: boolean; -} - -export interface MailboxPageParams { - root_id: string; - agent_id: string; - status?: string; - cursor?: null | { - root_id: string; - agent_id: string; - status: string; - revision: string; - offset: string; - }; - limit: number; - max_bytes: number; -} - -export interface MailboxReadParams { - root_id: string; - agent_id: string; - id: string; -} - -export interface ModelParams { - effort?: string; - model: string; - provider?: string; - persist_default: boolean; -} - -export interface ModelResult { - reload_pending?: boolean; - model: string; - provider: string; -} - -export interface PathParams { - path: string; -} - -export interface PathResult { - path: string; -} - -export interface PermissionConfigureParams { - external_permissions: boolean; -} - -export interface PermissionDecision { - command_id: string; - root_id: string; - permission_id: string; - allow: boolean; - reason?: string; - remember?: string; -} - -export interface PermissionDecisionParams { - decision: { - command_id: string; - root_id: string; - permission_id: string; - allow: boolean; - reason?: string; - remember?: string; - }; -} - -export interface PermissionDecisionResult { - operation_id: string; - lease_id: string; -} - -export interface PermissionRulesResult { - rules: - | null - | { - id: string; - root_id: string; - operation: string; - rule: string; - principal_id: string; - created_at: string; - }[]; - global: null | string[]; -} - -export interface PingResult { - generation: string; - build_id: string; -} - -export interface ProviderCatalogParams { - refresh?: boolean; - provider?: string; -} - -export interface ProviderCatalogsResult { - models: { - [k: string]: { - name?: string; - id?: string; - providers: null | string[]; - context?: number; - vision?: boolean; - }; - }; - providers: { - [k: string]: { - base_url: string; - available?: null | boolean; - }; - }; - catalogs: { - [k: string]: { - fetched_at: string; - base_url: string; - models: - | null - | { - pricing?: null | { - prompt: string; - completion: string; - input_cache_read?: string; - }; - pricing_known?: boolean; - cache_read_price_known?: boolean; - id: string; - context_length?: number; - max_completion_tokens?: number; - reasoning_efforts?: null | string[]; - in_price?: number; - out_price?: number; - cache_read_price?: number; - input_modalities?: null | string[]; - }[]; - }; - }; - errors?: { - [k: string]: string; - }; -} - -export interface ProviderConfiguration { - revision: string; - provider: string; - definition: { - name: string; - base_url: string; - api: string; - }; - custom: boolean; - credential: { - mode: string; - configured: boolean; - environment_variable?: string; - credential_path?: string; - available?: null | boolean; - }; - models: - | null - | { - alias: string; - id: string; - context?: number; - max_output?: number; - }[]; - removal_blockers: null | string[]; - discovery?: null | { - status: string; - message?: string; - model_count?: number; - }; -} - -export interface ProviderCreateParams { - revision: string; - provider: string; - definition: { - name: string; - base_url: string; - api: string; - }; - credential: { - mode: string; - key?: string; - environment_variable?: string; - }; - manual_model?: null | { - alias: string; - id: string; - context?: number; - max_output?: number; - }; - allow_unverified?: boolean; -} - -export interface ProviderDisconnectParams { - provider: string; - revision: string; -} - -export interface ProviderKeySetup { - revision: string; - provider: string; - key?: string; - environment: boolean; -} - -export interface ProviderList { - revision: string; - discovery_error?: string; - default_provider?: string; - providers: - | null - | { - id: string; - name: string; - custom: boolean; - methods: null | string[]; - status: { - provider: string; - configured: boolean; - key_source: string; - available?: null | boolean; - disabled?: boolean; - environment_variable?: string; - credential_path?: string; - auth_method?: string; - auth_state?: string; - account_id?: string; - plan?: string; - email?: string; - team_name?: string; - project_id?: string; - project_name?: string; - machine_key_name?: string; - warnings: null | string[]; - }; - recommended?: boolean; - suggested_model?: string; - category?: string; - family?: string; - key_url?: string; - }[]; - selection?: null | { - ready: boolean; - model: string; - provider: string; - reason: string; - }; -} - -export interface ProviderListParams { - model?: string; - provider?: string; -} - -export interface ProviderLoginBeginParams { - provider?: string; -} - -export interface ProviderLoginCreateParams { - flow_id: string; - name: string; -} - -export interface ProviderLoginList { - flows: - | null - | { - flow_id: string; - provider?: string; - state: string; - verification_url?: string; - user_code?: string; - email?: string; - teams: - | null - | { - id: string; - name: string; - }[]; - projects: - | null - | { - id: string; - name: string; - }[]; - team_id?: string; - project_id?: string; - expires_at: string; - error?: string; - }[]; -} - -export interface ProviderLoginParams { - flow_id: string; -} - -export interface ProviderLoginProjectParams { - flow_id: string; - project_id: string; -} - -export interface ProviderLoginStatus { - flow_id: string; - provider?: string; - state: string; - verification_url?: string; - user_code?: string; - email?: string; - teams: - | null - | { - id: string; - name: string; - }[]; - projects: - | null - | { - id: string; - name: string; - }[]; - team_id?: string; - project_id?: string; - expires_at: string; - error?: string; -} - -export interface ProviderLoginTeamParams { - flow_id: string; - team_id: string; -} - -export interface ProviderNameParams { - provider: string; -} - -export interface ProviderRemoveParams { - revision: string; - provider: string; -} - -export interface ProviderRemoveResult { - revision: string; - warning?: string; -} - -export interface ProviderStatus { - provider: string; - configured: boolean; - key_source: string; - available?: null | boolean; - disabled?: boolean; - environment_variable?: string; - credential_path?: string; - auth_method?: string; - auth_state?: string; - account_id?: string; - plan?: string; - email?: string; - team_name?: string; - project_id?: string; - project_name?: string; - machine_key_name?: string; - warnings: null | string[]; -} - -export interface ProviderUpdateParams { - revision: string; - provider: string; - name?: null | string; - base_url?: null | string; - credential?: null | { - mode: string; - key?: string; - environment_variable?: string; - }; - manual_model?: null | { - alias: string; - id: string; - context?: number; - max_output?: number; - }; - allow_unverified?: boolean; -} - -export interface ProviderValidateParams { - name: string; - base_url: string; - key: string; -} - -export interface ProviderValidateResult { - models: - | null - | { - id: string; - context_length?: number; - max_completion_tokens?: number; - reasoning_efforts?: null | string[]; - pricing?: null | { - prompt: string; - completion: string; - input_cache_read?: string; - }; - input_modalities?: null | string[]; - output_modalities?: null | string[]; - supports_tools?: null | boolean; - type?: string; - }[]; -} - -export interface QueryParams { - root_id?: string; - operation: string; - payload?: unknown; -} - -export interface QueryResult { - result?: unknown; - content?: null | { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - root_id?: string; -} - -export interface QuestionAnswerParams { - id: string; - answer: null | string[]; - dismissed: boolean; - answers?: - | null - | { - answer?: null | string[]; - dismissed?: boolean; - }[]; -} - -export interface RPCError { - data?: null | { - kind: string; - }; - code: number; - message: string; -} - -export interface ReplayParams { - root_id: string; - cursor: string; - limit?: number; -} - -export interface ReplayResult { - events: - | null - | { - subscription_id?: string; - root_id: string; - seq: string; - kind: string; - payload?: unknown; - }[]; - latest: string; - expired?: boolean; -} - -export interface Resolved { - id: string; - name: string; - dark: boolean; - colors: { - background: string; - foreground: string; - muted: string; - faint: string; - primary: string; - on_primary: string; - accent: string; - success: string; - warning: string; - error: string; - info: string; - link: string; - emphasis: string; - border: string; - border_focus: string; - diff_add: string; - diff_del: string; - panel: string; - element: string; - hover: string; - }; - syntax: { - keyword: string; - string: string; - number: string; - comment: string; - function: string; - type: string; - operator: string; - punctuation: string; - }; - markdown: { - heading: string; - strong: string; - code: string; - quote: string; - }; - code: { - foreground: string; - background: string; - tokens: { - [k: string]: { - color: string; - background: string; - bold: boolean; - italic: boolean; - underline: boolean; - }; - }; - }; - web?: null | { - navigation?: string; - quiet_border?: string; - code_background?: string; - inline_code_background?: string; - }; -} - -export interface RestartNotice { - generation: string; - cursors: { - [k: string]: string; - }; -} - -export interface RestartParams { - generation: string; -} - -export interface RewindParams { - expected_revision: string | null; - cut: number; -} - -export interface RewindResult { - cut: number; - restored_files: number; -} - -export interface RootCollectionPage { - root_id: string; - collection: string; - revision: string; - event_cursor: string; - items: - | null - | ({ - agent?: null | { - execution_engine: string; - last_turn?: null | { - turn_id?: string; - status: string; - started_at?: string; - finished_at?: string; - event_seq: string; - error?: string; - error_truncated?: boolean; - error_details?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - model_calls?: number; - compactions?: number; - last_activity_at?: string; - }; - id: string; - root_id: string; - parent_id: string; - name: string; - model: string; - provider: string; - effort: string; - cwd: string; - report: string; - status: string; - pending_mail: number; - lifecycle_phase: string; - blocking_reason: string; - terminal_cause: string; - allowed_controls: null | string[]; - }; - inbox?: null | { - delivery_seq?: string; - origin?: string; - command_client_id?: string; - command_id?: string; - steer_turn_id?: string; - preview?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - text: string; - truncated?: boolean; - attachments?: - | null - | { - kind: string; - name?: string; - content: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - attachment_count?: number; - }; - root_id: string; - agent_id: string; - seq: string; - kind: string; - status: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }; - blackboard?: null | { - key: string; - version: string; - author_agent_id: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }; - budget?: null | { - agent_id: string; - state: { - kind: string; - limit: string | null; - used: string; - reserved: string; - remaining: string | null; - uncertain: string; - incomplete: boolean; - }; - }; - capability?: null | { - id: string; - root_id: string; - agent_id: string; - issuer_agent_id: string; - operations: null | string[]; - scopes: null | string[]; - file_scope?: string; - file_issuer_id?: string; - file_issuer_generation?: string; - mcp: - | null - | { - server: string; - tool: string; - definition: string; - }[]; - mcp_all: boolean; - browser?: null | { - provider_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - profile_id: string; - attachment_id?: string; - attachment_generation?: string; - rights: null | string[]; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }; - browser_issuer_id?: string; - browser_issuer_generation?: number; - browser_delegation_only?: boolean; - generation: string; - status: string; - expires_at: string; - created_at: string; - updated_at: string; - }; - schedule?: null | { - id: number; - schedule: string; - prompt: string; - anchor: string; - last_fire: string; - }; - permission?: null | { - id: string; - agent_id: string; - operation_id: string; - operation: string; - canonical_path: string; - request_digest: string; - capability_id: string; - capability_generation: string; - status: string; - command: string; - rule: string; - }; - body?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - } & ( - | { - agent: null | { - execution_engine: string; - last_turn?: null | { - turn_id?: string; - status: string; - started_at?: string; - finished_at?: string; - event_seq: string; - error?: string; - error_truncated?: boolean; - error_details?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - model_calls?: number; - compactions?: number; - last_activity_at?: string; - }; - id: string; - root_id: string; - parent_id: string; - name: string; - model: string; - provider: string; - effort: string; - cwd: string; - report: string; - status: string; - pending_mail: number; - lifecycle_phase: string; - blocking_reason: string; - terminal_cause: string; - allowed_controls: null | string[]; - }; - } - | { - inbox: null | { - delivery_seq?: string; - origin?: string; - command_client_id?: string; - command_id?: string; - steer_turn_id?: string; - preview?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - text: string; - truncated?: boolean; - attachments?: - | null - | { - kind: string; - name?: string; - content: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - attachment_count?: number; - }; - root_id: string; - agent_id: string; - seq: string; - kind: string; - status: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }; - } - | { - blackboard: null | { - key: string; - version: string; - author_agent_id: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }; - } - | { - budget: null | { - agent_id: string; - state: { - kind: string; - limit: string | null; - used: string; - reserved: string; - remaining: string | null; - uncertain: string; - incomplete: boolean; - }; - }; - } - | { - capability: null | { - id: string; - root_id: string; - agent_id: string; - issuer_agent_id: string; - operations: null | string[]; - scopes: null | string[]; - file_scope?: string; - file_issuer_id?: string; - file_issuer_generation?: string; - mcp: - | null - | { - server: string; - tool: string; - definition: string; - }[]; - mcp_all: boolean; - browser?: null | { - provider_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - profile_id: string; - attachment_id?: string; - attachment_generation?: string; - rights: null | string[]; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }; - browser_issuer_id?: string; - browser_issuer_generation?: number; - browser_delegation_only?: boolean; - generation: string; - status: string; - expires_at: string; - created_at: string; - updated_at: string; - }; - } - | { - schedule: null | { - id: number; - schedule: string; - prompt: string; - anchor: string; - last_fire: string; - }; - } - | { - permission: null | { - id: string; - agent_id: string; - operation_id: string; - operation: string; - canonical_path: string; - request_digest: string; - capability_id: string; - capability_generation: string; - status: string; - command: string; - rule: string; - }; - } - | { - body: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - } - ))[]; - next_cursor?: null | { - root_id: string; - collection: string; - revision: string; - offset: string; - }; - has_more: boolean; -} - -export interface RootCollectionParams { - root_id: string; - collection: string; - cursor?: null | { - root_id: string; - collection: string; - revision: string; - offset: string; - }; - limit: number; - max_bytes: number; -} - -export interface RootIDResult { - root_id: string; -} - -export interface RootParams { - root_id: string; -} - -export interface RootSnapshot { - collection_revision?: string; - active_turns: { - [k: string]: string; - }; - omitted?: { - [k: string]: boolean; - }; - message_seqs: null | number[]; - first_message_seq?: number; - history_revision: string; - root_id: string; - cursor: string; - meta: { - execution_engine: string; - definition: string; - definition_revision: string; - id: string; - kind: string; - title: string; - model: string; - provider: string; - cwd: string; - goal: string; - forked_from: string; - fork_seq: number; - tags: null | string[]; - archived: boolean; - pinned: boolean; - effort: string; - usage_in: number; - usage_cached: number; - usage_out: number; - updated_at: string; - }; - messages: - | null - | { - presentation?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - context_part_index: number; - screenshot_part_index?: null | number; - }; - version: number; - turn_id?: string; - parts?: - | null - | { - id: string; - kind: string; - start?: number; - end?: number; - text?: string; - tool_name?: string; - status?: string; - call_id?: string; - hosts?: - | null - | { - invocation_id: string; - name: string; - summary?: string; - status: string; - duration?: string; - error?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - }[]; - omitted?: number; - }[]; - omitted?: number; - }; - role: string; - content: - | string - | { - type: string; - text?: string; - image_url?: null | { - url: string; - }; - w?: number; - h?: number; - }[]; - tool_calls?: - | null - | { - id: string; - type: string; - function: { - name: string; - arguments: string; - }; - duration_ms?: number; - exit_code?: number; - }[]; - tool_call_id?: string; - name?: string; - authored?: boolean; - sent_at?: null | string; - usage?: null | { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; - model?: string; - rewound_from?: string; - call_id?: string; - }[]; - presentation: - | null - | { - seq: string; - kind: string; - payload: unknown; - }[]; - agent_presentations: { - [k: string]: - | null - | { - seq: string; - kind: string; - payload: unknown; - }[]; - }; - agents: - | null - | { - execution_engine: string; - last_turn?: null | { - turn_id?: string; - status: string; - started_at?: string; - finished_at?: string; - event_seq: string; - error?: string; - error_truncated?: boolean; - error_details?: null | { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - model_calls?: number; - compactions?: number; - last_activity_at?: string; - }; - id: string; - root_id: string; - parent_id: string; - name: string; - model: string; - provider: string; - effort: string; - cwd: string; - report: string; - status: string; - pending_mail: number; - lifecycle_phase: string; - blocking_reason: string; - terminal_cause: string; - allowed_controls: null | string[]; - }[]; - inbox: - | null - | { - delivery_seq?: string; - origin?: string; - command_client_id?: string; - command_id?: string; - steer_turn_id?: string; - preview?: null | { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - text: string; - truncated?: boolean; - attachments?: - | null - | { - kind: string; - name?: string; - content: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - attachment_count?: number; - }; - root_id: string; - agent_id: string; - seq: string; - kind: string; - status: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - blackboard: - | null - | { - key: string; - version: string; - author_agent_id: string; - payload: { - inline?: unknown; - text?: null | string; - binary?: string | null; - reference_id: string; - digest: string; - size: string; - media_type: string; - source: string; - }; - }[]; - budgets: - | null - | { - agent_id: string; - state: { - kind: string; - limit: string | null; - used: string; - reserved: string; - remaining: string | null; - uncertain: string; - incomplete: boolean; - }; - }[]; - accounting?: { - root_id: string; - agent_id: string; - scope: string; - revision: string; - reported_cost_micros: string; - estimated_cost_micros: string; - reported_cost_calls: string; - estimated_cost_calls: string; - unknown_cost_calls: string; - reported_calls: string; - estimated_calls: string; - pending_calls: string; - }; - capabilities: - | null - | { - id: string; - root_id: string; - agent_id: string; - issuer_agent_id: string; - operations: null | string[]; - scopes: null | string[]; - file_scope?: string; - file_issuer_id?: string; - file_issuer_generation?: string; - mcp: - | null - | { - server: string; - tool: string; - definition: string; - }[]; - mcp_all: boolean; - browser?: null | { - provider_id: string; - provider_epoch: string; - tab_id: string; - tab_generation: string; - profile_id: string; - attachment_id?: string; - attachment_generation?: string; - rights: null | string[]; - preview?: null | { - host_id: string; - host_identity: string; - connection_generation: string; - environment_id: string; - loopback: string; - ports: null | number[]; - }; - }; - browser_issuer_id?: string; - browser_issuer_generation?: number; - browser_delegation_only?: boolean; - generation: string; - status: string; - expires_at: string; - created_at: string; - updated_at: string; - }[]; - schedules: - | null - | { - id: number; - schedule: string; - prompt: string; - anchor: string; - last_fire: string; - }[]; - upcoming_schedules?: - | null - | { - id: number; - next_fire: string; - prompt: string; - prompt_truncated?: boolean; - }[]; - upcoming_schedule_count?: null | number; - permissions: - | null - | { - id: string; - agent_id: string; - operation_id: string; - operation: string; - canonical_path: string; - request_digest: string; - capability_id: string; - capability_generation: string; - status: string; - command: string; - rule: string; - }[]; - questions: - | null - | { - turn_id?: string; - root_id?: string; - agent_id?: string; - sender_agent_id?: string; - inbox_seq?: string; - inbox_kind?: string; - delivery?: string; - message_id?: string; - phase?: string; - status?: string; - terminal_cause?: string; - command_client_id?: string; - command_id?: string; - operation_id?: string; - trace_id?: string; - schedule_id?: number; - slot?: string; - error?: string; - model_call?: null | { - id: string; - logical_id: string; - number: number; - purpose: string; - usage_source: string; - cost_source: string; - tokens: string; - cost_micros: string; - elapsed_millis: string; - exhausted: boolean; - }; - acknowledged_inbox?: string[]; - subscription_id?: string; - key?: string; - version?: string; - expected_version?: string; - restored?: null | string[]; - not_restored?: - | null - | { - name: string; - reason: string; - }[]; - attempt?: string; - budget_kind?: string; - amount?: string; - limit?: string; - used?: string; - reserved?: string; - capability_id?: string; - generation?: string; - permission_id?: string; - operation?: string; - canonical_path?: string; - request_digest?: string; - command?: string; - rule?: string; - rule_source?: string; - question_id?: string; - question?: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - questions?: - | null - | { - question: string; - options?: - | null - | { - label: string; - description?: string; - recommended?: boolean; - }[]; - multiple?: boolean; - }[]; - answer?: null | string[]; - dismissed?: boolean; - answers?: - | null - | { - answer?: null | string[]; - dismissed?: boolean; - }[]; - }[]; - permission_mode?: string; -} - -export interface RunConfigureParams { - system?: string; - max_turns?: number; - headless?: boolean; - cache_key?: string; -} - -export interface RuntimeConfiguration { - default_execution_engine: string; - disabled_providers?: null | string[]; - discovery?: null | { - status: string; - message?: string; - model_count?: number; - }; - remote_hosts?: - | null - | { - id: string; - name: string; - url: string; - runtime_id: string; - connect_on_launch: boolean; - }[]; - import_claude: boolean; - import_codex: boolean; - mcp_import_offered: boolean; - brand_icons: boolean; - revision: string; - default_model: string; - default_provider: string; - default_effort: string; - default_permission_mode?: string; - compact_model: string; - compact_provider: string; - compact_percent: number; - goal_max_rounds: number; - max_retries: number; -} - -export interface ScheduleCreateParams { - schedule: string; - prompt: string; -} - -export interface ScheduleDeleteParams { - schedule_id: number; -} - -export type ScheduleListResult = - | null - | { - id: number; - schedule: string; - prompt: string; - anchor: string; - last_fire: string; - }[]; - -export interface ScheduleResult { - schedule_id: number; -} - -export interface SessionCatalogPage { - revision: string; - items: - | null - | { - id: string; - kind: string; - title: string; - model: string; - provider: string; - cwd: string; - workspace_id?: string; - pinned: boolean; - archived: boolean; - updated_at: string; - truncated: boolean; - }[]; - next_cursor?: null | { - revision: string; - offset: string; - search?: string; - status: "active" | "archived" | "all"; - }; - has_more: boolean; -} - -export interface SessionCatalogParams { - search?: string; - status?: "active" | "archived" | "all"; - cursor?: null | { - revision: string; - offset: string; - search?: string; - status: "active" | "archived" | "all"; - }; - limit: number; - max_bytes: number; -} - -export type SessionListResult = - | null - | { - execution_engine: string; - definition: string; - definition_revision: string; - id: string; - kind: string; - title: string; - model: string; - provider: string; - cwd: string; - goal: string; - forked_from: string; - fork_seq: number; - tags: null | string[]; - archived: boolean; - pinned: boolean; - effort: string; - usage_in: number; - usage_cached: number; - usage_out: number; - updated_at: string; - }[]; - -export interface SessionMetadata { - root_id: string; - title: string; - cwd: string; - history_revision: string; - archived: boolean; -} - -export interface SessionPreviewResult { - root_id: string; - user: string; - assistant: string; -} - -export interface SessionSummariesParams { - /** - * @maxItems 32 - */ - root_ids: string[]; -} - -export interface SessionSummariesResult { - /** - * @maxItems 32 - */ - items: { - root_id: string; - missing: boolean; - archived: boolean; - title: string; - cwd: string; - workspace_id?: string; - running_agents: string; - queued_agents: string; - pending_permissions: string; - pending_questions: string; - truncated: boolean; - }[]; -} - -export interface SessionTitleChangedParams { - root_id: string; -} - -export interface SessionUpdateEvent { - archived?: null | boolean; - title?: string; - model?: string; - provider?: string; - effort?: string; - effort_changed?: boolean; - working_directory?: string; - permission_mode?: null | string; -} - -export interface ShellParams { - command: string; -} - -export interface SnapshotParams { - root_id: string; -} - -export interface SpanPage { - root_id: string; - spans: - | null - | { - id: string; - trace_id: string; - parent_id?: string; - root_id: string; - agent_id: string; - turn_id?: string; - kind: string; - name: string; - status: string; - start_ns: string; - end_ns: string; - attrs?: unknown; - links?: unknown; - updated_seq: string; - }[]; - next_seq: string; - has_more: boolean; - server_time_ns: string; -} - -export interface SpanRecord { - id: string; - trace_id: string; - parent_id?: string; - root_id: string; - agent_id: string; - turn_id?: string; - kind: string; - name: string; - status: string; - start_ns: string; - end_ns: string; - attrs?: unknown; - links?: unknown; - updated_seq: string; -} - -export interface StreamEvent { - part_id?: string; - display?: null | { - target?: string; - command?: string; - query?: string; - child_id?: string; - label?: string; - }; - accounting?: null | { - root_id: string; - agent_id: string; - scope: string; - revision: string; - reported_cost_micros: string; - estimated_cost_micros: string; - reported_cost_calls: string; - estimated_cost_calls: string; - unknown_cost_calls: string; - reported_calls: string; - estimated_calls: string; - pending_calls: string; - }; - usage?: null | { - used: number; - size: number; - usage: { - reported?: boolean; - cost?: null | number; - prompt_tokens: number; - completion_tokens: number; - prompt_tokens_details?: null | { - cached_tokens: number; - }; - completion_tokens_details?: null | { - reasoning_tokens: number; - }; - }; - }; - agent_id?: string; - turn_id?: string; - invocation_id?: string; - operation_id?: string; - host_status?: string; - id?: string; - name?: string; - text?: string; - args?: string; - result?: string; -} - -export interface SubmitPayload { - design_context?: null | { - context_attachment_id: string; - screenshot_attachment_id?: string; - elements: - | null - | { - label: string; - selector?: string; - }[]; - element_count: number; - page_url?: string; - page_title?: string; - }; - text: string; - parts?: - | null - | { - type: string; - text?: string; - image_url?: null | { - url: string; - }; - w?: number; - h?: number; - }[]; - attachments?: - | null - | { - kind: "image" | "text"; - content: { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - name?: string; - }[]; -} - -export interface SubscribeParams { - root_id: string; - subscription_id: string; - cursor: string; -} - -export interface SubscribeResult { - subscription_id: string; - cursor: string; -} - -export interface SubscriptionFailure { - subscription_id: string; - root_id: string; - error: null | { - data?: null | { - kind: string; - }; - code: number; - message: string; - }; -} - -export interface TerminalAttachParams { - id: string; - cursor: string; -} - -export interface TerminalAttachResult { - cursor: string; - cwd: string; - cols: number; - rows: number; - exited: boolean; - exit_code?: number; - signal?: string; -} - -export interface TerminalDetachedParams { - id: string; -} - -export interface TerminalExitedParams { - id: string; - exit_code: number; - signal?: string; -} - -export interface TerminalIDParams { - id: string; -} - -export interface TerminalInputParams { - id: string; - bytes: string | null; -} - -export interface TerminalOpenParams { - cwd?: string; - root_id?: string; - cols: number; - rows: number; -} - -export interface TerminalOpenResult { - id: string; - shell: string; - cwd: string; -} - -export interface TerminalOutputParams { - id: string; - cursor: string; - bytes: string | null; -} - -export interface TerminalResizeParams { - id: string; - cols: number; - rows: number; -} - -export interface TerminalWriteParams { - id: string; - bytes: string | null; -} - -export interface TextParams { - text: string; -} - -export interface TextResult { - text: string; - output?: unknown; -} - -export interface TitleParams { - title: string; -} - -export interface TitleResult { - title: string; -} - -export interface ToolCallParams { - tool: string; - arguments: unknown; -} - -export interface ToolCancelParams { - invocation_id: string; - generation: string; - reason: string; -} - -export interface ToolConfigureParams { - deny_permissions: boolean; -} - -export interface ToolInvokeParams { - invocation_id: string; - definition: string; - revision: string; - generation: string; - root_id: string; - agent_id: string; - turn_id: string; - tool: string; - input: unknown; - deadline_millis: string; -} - -export interface ToolProgressParams { - invocation_id: string; - generation: string; - text: string; -} - -export interface ToolResultParams { - invocation_id: string; - generation: string; - output?: unknown; - error?: string; -} - -export type ToolSchemaResult = - | null - | { - type: string; - function: { - name: string; - description: string; - parameters: unknown; - }; - }[]; - -export interface TraceExportParams { - root_id: string; - trace_id?: string; -} - -export interface TraceExportResult { - content: { - reference_id: string; - digest: string; - size: string; - media_type?: string; - source?: string; - }; - spans: number; - traces: number; -} - -export interface TracePageParams { - root_id: string; - trace_id?: string; - after_seq?: string; - limit?: number; - roots_only?: boolean; -} - -export interface UnsubscribeParams { - subscription_id: string; -} - -export interface UploadBeginParams { - upload_id: string; - root_id: string; - agent_id?: string; - expected_digest: string; - size: string; - media_type?: string; - source?: string; -} - -export interface UploadChunkParams { - upload_id: string; - offset: string; - data: string | null; -} - -export interface UploadFinishParams { - upload_id: string; -} - -export type UserHistoryResult = null | string[]; - -export interface ContractTypes { - Accepted: Accepted; - AgentCancelParams: AgentCancelParams; - AgentInputParams: AgentInputParams; - AgentListResult: AgentListResult; - AgentSubmitResult: AgentSubmitResult; - AgentTranscriptResult: AgentTranscriptResult; - ArchiveParams: ArchiveParams; - ArchiveResult: ArchiveResult; - BoundedTranscriptPage: BoundedTranscriptPage; - BrowserCommand: BrowserCommand; - BrowserCommandCancel: BrowserCommandCancel; - BrowserCommandResultParams: BrowserCommandResultParams; - BrowserDriverParams: BrowserDriverParams; - BrowserInventoryRequest: BrowserInventoryRequest; - BrowserInventoryResultParams: BrowserInventoryResultParams; - BrowserProviderBindParams: BrowserProviderBindParams; - BrowserProviderBindResult: BrowserProviderBindResult; - BrowserProviderEventParams: BrowserProviderEventParams; - BrowserProviderRevoked: BrowserProviderRevoked; - BrowserProviderUnbindParams: BrowserProviderUnbindParams; - BrowserStatusResult: BrowserStatusResult; - BudgetCapParams: BudgetCapParams; - BudgetState: BudgetState; - CancelParams: CancelParams; - CapabilityRecord: CapabilityRecord; - CatalogResult: CatalogResult; - CatalogRevision: CatalogRevision; - CheckpointParams: CheckpointParams; - ClearHistoryParams: ClearHistoryParams; - CommandParams: CommandParams; - CommandResult: CommandResult; - CommandStatusParams: CommandStatusParams; - CompactionListResult: CompactionListResult; - CompactionParams: CompactionParams; - CompactionResult: CompactionResult; - CompactionRetryResult: CompactionRetryResult; - CompactionSettingsResult: CompactionSettingsResult; - CompletionParams: CompletionParams; - CompletionResult: CompletionResult; - ComputerAppParams: ComputerAppParams; - ComputerStatusResult: ComputerStatusResult; - ConfigurationUpdate: ConfigurationUpdate; - ContentEventPayload: ContentEventPayload; - ContentHandle: ContentHandle; - ContentReadParams: ContentReadParams; - ContentReadResult: ContentReadResult; - ContextAuditResult: ContextAuditResult; - CreateSessionParams: CreateSessionParams; - DefinitionList: DefinitionList; - DefinitionParams: DefinitionParams; - DefinitionRecord: DefinitionRecord; - DefinitionRegisterParams: DefinitionRegisterParams; - DefinitionRegisterResult: DefinitionRegisterResult; - EffortParams: EffortParams; - EffortResult: EffortResult; - Empty: Empty; - EmptyParams: EmptyParams; - EventNotification: EventNotification; - ExecutorBindParams: ExecutorBindParams; - ExecutorBindResult: ExecutorBindResult; - ExecutorPendingParams: ExecutorPendingParams; - ExecutorPendingResult: ExecutorPendingResult; - ForkParams: ForkParams; - GatewayStatus: GatewayStatus; - GoalContextParams: GoalContextParams; - GoalResult: GoalResult; - HistoryPageParams: HistoryPageParams; - HookInvokeParams: HookInvokeParams; - HookResultParams: HookResultParams; - HostAttentionParams: HostAttentionParams; - HostAttentionResult: HostAttentionResult; - HostDirectoryParams: HostDirectoryParams; - HostDirectoryPickParams: HostDirectoryPickParams; - HostDirectoryPickResult: HostDirectoryPickResult; - HostDirectoryResult: HostDirectoryResult; - HostSkillCompletionParams: HostSkillCompletionParams; - HostThemeResolveParams: HostThemeResolveParams; - IDParams: IDParams; - InboxControlResult: InboxControlResult; - InboxRemoveParams: InboxRemoveParams; - InboxSteerParams: InboxSteerParams; - InitializeParams: InitializeParams; - InitializeResult: InitializeResult; - LSPListResult: LSPListResult; - LifecycleEvent: LifecycleEvent; - ListParams: ListParams; - MCPAttachParams: MCPAttachParams; - MCPBrandIconsParams: MCPBrandIconsParams; - MCPBrandIconsResult: MCPBrandIconsResult; - MCPImportApplyParams: MCPImportApplyParams; - MCPImportApplyResult: MCPImportApplyResult; - MCPImportCandidatesParams: MCPImportCandidatesParams; - MCPImportCandidatesResult: MCPImportCandidatesResult; - MCPImportParams: MCPImportParams; - MCPImportStatusResult: MCPImportStatusResult; - MCPListResult: MCPListResult; - MCPRefreshResult: MCPRefreshResult; - MCPServerParams: MCPServerParams; - MailboxInspection: MailboxInspection; - MailboxPage: MailboxPage; - MailboxPageParams: MailboxPageParams; - MailboxReadParams: MailboxReadParams; - ModelParams: ModelParams; - ModelResult: ModelResult; - PathParams: PathParams; - PathResult: PathResult; - PermissionConfigureParams: PermissionConfigureParams; - PermissionDecision: PermissionDecision; - PermissionDecisionParams: PermissionDecisionParams; - PermissionDecisionResult: PermissionDecisionResult; - PermissionRulesResult: PermissionRulesResult; - PingResult: PingResult; - ProviderCatalogParams: ProviderCatalogParams; - ProviderCatalogsResult: ProviderCatalogsResult; - ProviderConfiguration: ProviderConfiguration; - ProviderCreateParams: ProviderCreateParams; - ProviderDisconnectParams: ProviderDisconnectParams; - ProviderKeySetup: ProviderKeySetup; - ProviderList: ProviderList; - ProviderListParams: ProviderListParams; - ProviderLoginBeginParams: ProviderLoginBeginParams; - ProviderLoginCreateParams: ProviderLoginCreateParams; - ProviderLoginList: ProviderLoginList; - ProviderLoginParams: ProviderLoginParams; - ProviderLoginProjectParams: ProviderLoginProjectParams; - ProviderLoginStatus: ProviderLoginStatus; - ProviderLoginTeamParams: ProviderLoginTeamParams; - ProviderNameParams: ProviderNameParams; - ProviderRemoveParams: ProviderRemoveParams; - ProviderRemoveResult: ProviderRemoveResult; - ProviderStatus: ProviderStatus; - ProviderUpdateParams: ProviderUpdateParams; - ProviderValidateParams: ProviderValidateParams; - ProviderValidateResult: ProviderValidateResult; - QueryParams: QueryParams; - QueryResult: QueryResult; - QuestionAnswerParams: QuestionAnswerParams; - RPCError: RPCError; - ReplayParams: ReplayParams; - ReplayResult: ReplayResult; - Resolved: Resolved; - RestartNotice: RestartNotice; - RestartParams: RestartParams; - RewindParams: RewindParams; - RewindResult: RewindResult; - RootCollectionPage: RootCollectionPage; - RootCollectionParams: RootCollectionParams; - RootIDResult: RootIDResult; - RootParams: RootParams; - RootSnapshot: RootSnapshot; - RunConfigureParams: RunConfigureParams; - RuntimeConfiguration: RuntimeConfiguration; - ScheduleCreateParams: ScheduleCreateParams; - ScheduleDeleteParams: ScheduleDeleteParams; - ScheduleListResult: ScheduleListResult; - ScheduleResult: ScheduleResult; - SessionCatalogPage: SessionCatalogPage; - SessionCatalogParams: SessionCatalogParams; - SessionListResult: SessionListResult; - SessionMetadata: SessionMetadata; - SessionPreviewResult: SessionPreviewResult; - SessionSummariesParams: SessionSummariesParams; - SessionSummariesResult: SessionSummariesResult; - SessionTitleChangedParams: SessionTitleChangedParams; - SessionUpdateEvent: SessionUpdateEvent; - ShellParams: ShellParams; - SnapshotParams: SnapshotParams; - SpanPage: SpanPage; - SpanRecord: SpanRecord; - StreamEvent: StreamEvent; - SubmitPayload: SubmitPayload; - SubscribeParams: SubscribeParams; - SubscribeResult: SubscribeResult; - SubscriptionFailure: SubscriptionFailure; - TerminalAttachParams: TerminalAttachParams; - TerminalAttachResult: TerminalAttachResult; - TerminalDetachedParams: TerminalDetachedParams; - TerminalExitedParams: TerminalExitedParams; - TerminalIDParams: TerminalIDParams; - TerminalInputParams: TerminalInputParams; - TerminalOpenParams: TerminalOpenParams; - TerminalOpenResult: TerminalOpenResult; - TerminalOutputParams: TerminalOutputParams; - TerminalResizeParams: TerminalResizeParams; - TerminalWriteParams: TerminalWriteParams; - TextParams: TextParams; - TextResult: TextResult; - TitleParams: TitleParams; - TitleResult: TitleResult; - ToolCallParams: ToolCallParams; - ToolCancelParams: ToolCancelParams; - ToolConfigureParams: ToolConfigureParams; - ToolInvokeParams: ToolInvokeParams; - ToolProgressParams: ToolProgressParams; - ToolResultParams: ToolResultParams; - ToolSchemaResult: ToolSchemaResult; - TraceExportParams: TraceExportParams; - TraceExportResult: TraceExportResult; - TracePageParams: TracePageParams; - UnsubscribeParams: UnsubscribeParams; - UploadBeginParams: UploadBeginParams; - UploadChunkParams: UploadChunkParams; - UploadFinishParams: UploadFinishParams; - UserHistoryResult: UserHistoryResult; -} -export interface EventPayloadTypes { - "agent.admitted": LifecycleEvent | ContentEventPayload; - "agent.prompt.queued": LifecycleEvent | ContentEventPayload; - "agent.subtree.deleted": LifecycleEvent | ContentEventPayload; - "agent.subtree.stopped": LifecycleEvent | ContentEventPayload; - "agent.turn.cancelled": LifecycleEvent | ContentEventPayload; - "agent.turn.failed": LifecycleEvent | ContentEventPayload; - "agent.turn.interrupted": LifecycleEvent | ContentEventPayload; - "agent.turn.started": LifecycleEvent | ContentEventPayload; - "agent.turn.succeeded": LifecycleEvent | ContentEventPayload; - "blackboard.append": LifecycleEvent | ContentEventPayload; - "blackboard.cas": LifecycleEvent | ContentEventPayload; - "blackboard.set": LifecycleEvent | ContentEventPayload; - "budget.active_child.reserved": LifecycleEvent | ContentEventPayload; - "budget.capped": LifecycleEvent | ContentEventPayload; - "capability.delegated": LifecycleEvent | ContentEventPayload; - "capability.revoked": LifecycleEvent | ContentEventPayload; - "command.cancelled": LifecycleEvent | ContentEventPayload; - "command.control.queued": LifecycleEvent | ContentEventPayload; - "command.failed": LifecycleEvent | ContentEventPayload; - "command.interrupted": LifecycleEvent | ContentEventPayload; - "command.queued": LifecycleEvent | ContentEventPayload; - "command.running": LifecycleEvent | ContentEventPayload; - "command.succeeded": LifecycleEvent | ContentEventPayload; - "command.waiting": LifecycleEvent | ContentEventPayload; - "goal.continued": LifecycleEvent | ContentEventPayload; - "inbox.consumed": LifecycleEvent | ContentEventPayload; - "inbox.failed": LifecycleEvent | ContentEventPayload; - "inbox.queued": LifecycleEvent | ContentEventPayload; - "inbox.removed": LifecycleEvent | ContentEventPayload; - "inbox.running": LifecycleEvent | ContentEventPayload; - "inbox.steering": LifecycleEvent | ContentEventPayload; - "message.deferred": LifecycleEvent | ContentEventPayload; - "message.delivered": LifecycleEvent | ContentEventPayload; - "message.done": LifecycleEvent | ContentEventPayload; - "message.queued": LifecycleEvent | ContentEventPayload; - "message.updated": LifecycleEvent | ContentEventPayload; - "model.call.corrected": LifecycleEvent | ContentEventPayload; - "model.call.interrupted": LifecycleEvent | ContentEventPayload; - "model.call.settled": LifecycleEvent | ContentEventPayload; - "model.call.started": LifecycleEvent | ContentEventPayload; - "permission.auto_approved": LifecycleEvent | ContentEventPayload; - "permission.pending": LifecycleEvent | ContentEventPayload; - "question.answered": LifecycleEvent | ContentEventPayload; - "question.closed": LifecycleEvent | ContentEventPayload; - "question.pending": LifecycleEvent | ContentEventPayload; - "root.failed": LifecycleEvent | ContentEventPayload; - "root.interrupted": LifecycleEvent | ContentEventPayload; - "root.stopped": LifecycleEvent | ContentEventPayload; - "schedule.fired": LifecycleEvent | ContentEventPayload; - "scratch.restored": LifecycleEvent | ContentEventPayload; - "session.archived.updated": SessionUpdateEvent | ContentEventPayload; - "session.cwd.updated": SessionUpdateEvent | ContentEventPayload; - "session.effort.updated": SessionUpdateEvent | ContentEventPayload; - "session.model.updated": SessionUpdateEvent | ContentEventPayload; - "session.permission_mode.updated": SessionUpdateEvent | ContentEventPayload; - "session.reload.failed": LifecycleEvent | ContentEventPayload; - "session.title.updated": SessionUpdateEvent | ContentEventPayload; - "span.ended": SpanRecord | ContentEventPayload; - "span.started": SpanRecord | ContentEventPayload; - "state.private.append": LifecycleEvent | ContentEventPayload; - "state.private.cas": LifecycleEvent | ContentEventPayload; - "state.private.set": LifecycleEvent | ContentEventPayload; - "stream.accounting": StreamEvent | ContentEventPayload; - "stream.cell.host": StreamEvent | ContentEventPayload; - "stream.cell.host.started": StreamEvent | ContentEventPayload; - "stream.discard": StreamEvent | ContentEventPayload; - "stream.hook.decision": StreamEvent | ContentEventPayload; - "stream.notice": StreamEvent | ContentEventPayload; - "stream.reasoning": StreamEvent | ContentEventPayload; - "stream.terminal.awaiting": StreamEvent | ContentEventPayload; - "stream.terminal.completed": StreamEvent | ContentEventPayload; - "stream.terminal.output": StreamEvent | ContentEventPayload; - "stream.terminal.started": StreamEvent | ContentEventPayload; - "stream.text": StreamEvent | ContentEventPayload; - "stream.tool.call": StreamEvent | ContentEventPayload; - "stream.tool.completed": StreamEvent | ContentEventPayload; - "stream.tool.output": StreamEvent | ContentEventPayload; - "stream.tool.progress": StreamEvent | ContentEventPayload; - "stream.tool.started": StreamEvent | ContentEventPayload; - "stream.usage": StreamEvent | ContentEventPayload; - "subscription.cancelled": LifecycleEvent | ContentEventPayload; - "subscription.created": LifecycleEvent | ContentEventPayload; - "turn.cancelled": LifecycleEvent | ContentEventPayload; - "turn.failed": LifecycleEvent | ContentEventPayload; - "turn.interrupted": LifecycleEvent | ContentEventPayload; - "turn.started": LifecycleEvent | ContentEventPayload; - "turn.succeeded": LifecycleEvent | ContentEventPayload; -} -export interface RpcMethods { - "browser.command.result": { params: BrowserCommandResultParams; result: Accepted; execution: "ephemeral"; permission: "browser-provider"; sensitive: false }; - "browser.inventory.result": { params: BrowserInventoryResultParams; result: Accepted; execution: "ephemeral"; permission: "browser-provider"; sensitive: false }; - "browser.provider.bind": { params: BrowserProviderBindParams; result: BrowserProviderBindResult; execution: "ephemeral"; permission: "browser-provider"; sensitive: false }; - "browser.provider.event": { params: BrowserProviderEventParams; result: Accepted; execution: "ephemeral"; permission: "browser-provider"; sensitive: false }; - "browser.provider.unbind": { params: BrowserProviderUnbindParams; result: Accepted; execution: "ephemeral"; permission: "browser-provider"; sensitive: false }; - "command.status": { params: CommandStatusParams; result: CommandResult; execution: "query"; permission: "client-command-namespace"; sensitive: false }; - "command.submit": { params: CommandParams; result: CommandResult; execution: "command"; permission: "operation-specific"; sensitive: false }; - "config.get": { params: Empty; result: RuntimeConfiguration; execution: "query"; permission: "none"; sensitive: false }; - "config.update": { params: ConfigurationUpdate; result: RuntimeConfiguration; execution: "ephemeral"; permission: "configuration-revision"; sensitive: false }; - "content.read": { params: ContentReadParams; result: ContentReadResult; execution: "query"; permission: "root-agent-content-grant"; sensitive: false }; - "daemon.ping": { params: Empty; result: PingResult; execution: "query"; permission: "none"; sensitive: false }; - "daemon.restart": { params: RestartParams; result: Empty; execution: "lifecycle"; permission: "armed-generation"; sensitive: false }; - "daemon.stop": { params: RestartParams; result: Empty; execution: "lifecycle"; permission: "armed-generation"; sensitive: false }; - "definitions.get": { params: DefinitionParams; result: DefinitionRecord; execution: "query"; permission: "host-runtime"; sensitive: false }; - "definitions.list": { params: Empty; result: DefinitionList; execution: "query"; permission: "host-runtime"; sensitive: false }; - "definitions.register": { params: DefinitionRegisterParams; result: DefinitionRegisterResult; execution: "ephemeral"; permission: "host-runtime"; sensitive: false }; - "events.replay": { params: ReplayParams; result: ReplayResult; execution: "query"; permission: "root-association"; sensitive: false }; - "events.subscribe": { params: SubscribeParams; result: SubscribeResult; execution: "subscription"; permission: "root-association"; sensitive: false }; - "events.unsubscribe": { params: UnsubscribeParams; result: Empty; execution: "subscription"; permission: "connection-subscription"; sensitive: false }; - "executor.bind": { params: ExecutorBindParams; result: ExecutorBindResult; execution: "ephemeral"; permission: "host-runtime"; sensitive: false }; - "executor.pending": { params: ExecutorPendingParams; result: ExecutorPendingResult; execution: "query"; permission: "executor-lease"; sensitive: false }; - "gateway.status": { params: Empty; result: GatewayStatus; execution: "query"; permission: "none"; sensitive: false }; - "history.page": { params: HistoryPageParams; result: BoundedTranscriptPage; execution: "query"; permission: "root-agent-association"; sensitive: false }; - "hook.result": { params: HookResultParams; result: Accepted; execution: "ephemeral"; permission: "executor-lease"; sensitive: false }; - "host.attention": { params: HostAttentionParams; result: HostAttentionResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "host.directories.list": { params: HostDirectoryParams; result: HostDirectoryResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "host.directory.pick": { params: HostDirectoryPickParams; result: HostDirectoryPickResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "host.skills.complete": { params: HostSkillCompletionParams; result: CompletionResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "host.themes.list": { params: EmptyParams; result: CatalogResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "host.themes.resolve": { params: HostThemeResolveParams; result: Resolved; execution: "query"; permission: "host-runtime"; sensitive: false }; - "initialize": { params: InitializeParams; result: InitializeResult; execution: "query"; permission: "none"; sensitive: false }; - "mailbox.list": { params: MailboxPageParams; result: MailboxPage; execution: "query"; permission: "root-agent-association"; sensitive: false }; - "mailbox.read": { params: MailboxReadParams; result: MailboxInspection; execution: "query"; permission: "root-agent-association"; sensitive: false }; - "mcp.brand.icons": { params: MCPBrandIconsParams; result: MCPBrandIconsResult; execution: "query"; permission: "host-configuration"; sensitive: false }; - "mcp.import.apply": { params: MCPImportApplyParams; result: MCPImportApplyResult; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "mcp.import.candidates": { params: MCPImportCandidatesParams; result: MCPImportCandidatesResult; execution: "query"; permission: "host-configuration"; sensitive: false }; - "operation.invoke": { params: QueryParams; result: QueryResult; execution: "ephemeral"; permission: "operation-specific"; sensitive: true }; - "permission.decide": { params: PermissionDecisionParams; result: PermissionDecisionResult; execution: "ephemeral"; permission: "trusted-client-decision"; sensitive: false }; - "provider.create": { params: ProviderCreateParams; result: ProviderConfiguration; execution: "ephemeral"; permission: "configuration-revision"; sensitive: true }; - "provider.disconnect": { params: ProviderDisconnectParams; result: ProviderStatus; execution: "ephemeral"; permission: "configuration-revision"; sensitive: false }; - "provider.discover": { params: ProviderListParams; result: ProviderList; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.get": { params: ProviderNameParams; result: ProviderConfiguration; execution: "query"; permission: "host-configuration"; sensitive: false }; - "provider.key.rotate": { params: ProviderNameParams; result: ProviderStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: true }; - "provider.key.set": { params: ProviderKeySetup; result: RuntimeConfiguration; execution: "ephemeral"; permission: "configuration-revision"; sensitive: true }; - "provider.list": { params: ProviderListParams; result: ProviderList; execution: "query"; permission: "host-configuration"; sensitive: false }; - "provider.login.begin": { params: ProviderLoginBeginParams; result: ProviderLoginStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.login.cancel": { params: ProviderLoginParams; result: ProviderLoginStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.login.list": { params: Empty; result: ProviderLoginList; execution: "query"; permission: "host-configuration"; sensitive: false }; - "provider.login.project.create": { params: ProviderLoginCreateParams; result: ProviderLoginStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.login.project.select": { params: ProviderLoginProjectParams; result: ProviderLoginStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.login.status": { params: ProviderLoginParams; result: ProviderLoginStatus; execution: "query"; permission: "none"; sensitive: false }; - "provider.login.team.select": { params: ProviderLoginTeamParams; result: ProviderLoginStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.logout": { params: ProviderNameParams; result: ProviderStatus; execution: "ephemeral"; permission: "host-configuration"; sensitive: false }; - "provider.remove": { params: ProviderRemoveParams; result: ProviderRemoveResult; execution: "ephemeral"; permission: "configuration-revision"; sensitive: false }; - "provider.status": { params: ProviderNameParams; result: ProviderStatus; execution: "query"; permission: "host-configuration"; sensitive: false }; - "provider.update": { params: ProviderUpdateParams; result: ProviderConfiguration; execution: "ephemeral"; permission: "configuration-revision"; sensitive: true }; - "provider.validate": { params: ProviderValidateParams; result: ProviderValidateResult; execution: "ephemeral"; permission: "host-configuration"; sensitive: true }; - "query": { params: QueryParams; result: QueryResult; execution: "query"; permission: "operation-specific"; sensitive: false }; - "root.collection": { params: RootCollectionParams; result: RootCollectionPage; execution: "query"; permission: "root-association"; sensitive: false }; - "root.snapshot": { params: SnapshotParams; result: RootSnapshot; execution: "query"; permission: "root-association"; sensitive: false }; - "sessions.get": { params: RootParams; result: SessionMetadata; execution: "query"; permission: "root-association"; sensitive: false }; - "sessions.list": { params: SessionCatalogParams; result: SessionCatalogPage; execution: "query"; permission: "host-runtime"; sensitive: false }; - "sessions.revision": { params: EmptyParams; result: CatalogRevision; execution: "query"; permission: "host-runtime"; sensitive: false }; - "sessions.summaries": { params: SessionSummariesParams; result: SessionSummariesResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "terminal.attach": { params: TerminalAttachParams; result: TerminalAttachResult; execution: "ephemeral"; permission: "host-terminal"; sensitive: false }; - "terminal.close": { params: TerminalIDParams; result: Accepted; execution: "ephemeral"; permission: "host-terminal"; sensitive: false }; - "terminal.open": { params: TerminalOpenParams; result: TerminalOpenResult; execution: "ephemeral"; permission: "host-terminal"; sensitive: false }; - "terminal.resize": { params: TerminalResizeParams; result: Accepted; execution: "ephemeral"; permission: "host-terminal"; sensitive: false }; - "terminal.write": { params: TerminalWriteParams; result: Accepted; execution: "ephemeral"; permission: "host-terminal"; sensitive: true }; - "tool.progress": { params: ToolProgressParams; result: Accepted; execution: "ephemeral"; permission: "executor-lease"; sensitive: false }; - "tool.result": { params: ToolResultParams; result: Accepted; execution: "ephemeral"; permission: "executor-lease"; sensitive: false }; - "trace.export": { params: TraceExportParams; result: TraceExportResult; execution: "query"; permission: "root-association"; sensitive: false }; - "trace.page": { params: TracePageParams; result: SpanPage; execution: "query"; permission: "root-association"; sensitive: false }; - "upload.begin": { params: UploadBeginParams; result: Accepted; execution: "ephemeral"; permission: "content-grant"; sensitive: false }; - "upload.chunk": { params: UploadChunkParams; result: Accepted; execution: "ephemeral"; permission: "connection-upload"; sensitive: false }; - "upload.finish": { params: UploadFinishParams; result: ContentHandle; execution: "ephemeral"; permission: "content-grant"; sensitive: false }; - "workspace.complete": { params: CompletionParams; result: CompletionResult; execution: "query"; permission: "root-agent-association"; sensitive: false }; -} -export interface RuntimeOperations { - "agent.control": { params: IDParams; result: Empty; execution: "command"; permission: "agent-authority"; sensitive: false }; - "agent.delete": { params: IDParams; result: Empty; execution: "command"; permission: "agent-authority"; sensitive: false }; - "agent.submit": { params: AgentInputParams; result: AgentSubmitResult; execution: "command"; permission: "agent-admission"; sensitive: false }; - "agent.transcript": { params: IDParams; result: AgentTranscriptResult; execution: "query"; permission: "human-transcript-inspection"; sensitive: false }; - "agent.turn.cancel": { params: AgentCancelParams; result: Empty; execution: "command"; permission: "target-turn"; sensitive: false }; - "agents.list": { params: EmptyParams; result: AgentListResult; execution: "query"; permission: "root-association"; sensitive: false }; - "browser.set_driver": { params: BrowserDriverParams; result: BrowserStatusResult; execution: "command"; permission: "host-configuration"; sensitive: false }; - "browser.status": { params: EmptyParams; result: BrowserStatusResult; execution: "query"; permission: "root-association"; sensitive: false }; - "budget.cap": { params: BudgetCapParams; result: BudgetState; execution: "command"; permission: "budget-authority"; sensitive: false }; - "cancel": { params: CancelParams; result: Empty; execution: "command"; permission: "target-turn"; sensitive: false }; - "capability.revoke": { params: IDParams; result: CapabilityRecord; execution: "command"; permission: "capability-authority"; sensitive: false }; - "compaction.configure": { params: CompactionParams; result: CompactionSettingsResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "computer.allow": { params: ComputerAppParams; result: ComputerStatusResult; execution: "command"; permission: "human-computer-policy"; sensitive: false }; - "computer.deny": { params: ComputerAppParams; result: ComputerStatusResult; execution: "command"; permission: "human-computer-policy"; sensitive: false }; - "computer.status": { params: EmptyParams; result: ComputerStatusResult; execution: "query"; permission: "root-association"; sensitive: false }; - "context.audit": { params: EmptyParams; result: ContextAuditResult; execution: "query"; permission: "root-association"; sensitive: false }; - "daemon.checkpoint": { params: CheckpointParams; result: RestartNotice; execution: "command"; permission: "host-runtime"; sensitive: false }; - "goal.from-context": { params: GoalContextParams; result: GoalResult; execution: "command"; permission: "root-admission"; sensitive: false }; - "goal.run": { params: TextParams; result: GoalResult; execution: "command"; permission: "root-admission"; sensitive: false }; - "goal.set": { params: TextParams; result: GoalResult; execution: "command"; permission: "root-admission"; sensitive: false }; - "history.clear": { params: ClearHistoryParams; result: Empty; execution: "command"; permission: "root-idle"; sensitive: false }; - "history.compact": { params: EmptyParams; result: CompactionResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "history.compact.log": { params: EmptyParams; result: CompactionListResult; execution: "query"; permission: "root-association"; sensitive: false }; - "history.compact.retry": { params: EmptyParams; result: CompactionRetryResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "history.rewind": { params: RewindParams; result: RewindResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "history.user.list": { params: EmptyParams; result: UserHistoryResult; execution: "query"; permission: "root-association"; sensitive: false }; - "inbox.remove": { params: InboxRemoveParams; result: InboxControlResult; execution: "command"; permission: "root-association"; sensitive: false }; - "inbox.steer": { params: InboxSteerParams; result: InboxControlResult; execution: "command"; permission: "root-association"; sensitive: false }; - "lsp.status": { params: EmptyParams; result: LSPListResult; execution: "query"; permission: "root-association"; sensitive: false }; - "mcp.attach": { params: MCPAttachParams; result: Empty; execution: "ephemeral"; permission: "delegated-mcp-authority"; sensitive: true }; - "mcp.disable": { params: MCPServerParams; result: Empty; execution: "command"; permission: "delegated-mcp-authority"; sensitive: false }; - "mcp.enable": { params: MCPServerParams; result: Empty; execution: "command"; permission: "delegated-mcp-authority"; sensitive: false }; - "mcp.import.configure": { params: MCPImportParams; result: MCPImportStatusResult; execution: "command"; permission: "host-configuration"; sensitive: false }; - "mcp.import.status": { params: EmptyParams; result: MCPImportStatusResult; execution: "query"; permission: "host-configuration"; sensitive: false }; - "mcp.reconnect": { params: MCPServerParams; result: Empty; execution: "command"; permission: "delegated-mcp-authority"; sensitive: false }; - "mcp.refresh": { params: EmptyParams; result: MCPRefreshResult; execution: "command"; permission: "root-association"; sensitive: false }; - "mcp.status": { params: EmptyParams; result: MCPListResult; execution: "query"; permission: "root-association"; sensitive: false }; - "permission.forget": { params: IDParams; result: Empty; execution: "command"; permission: "rule-authority"; sensitive: false }; - "permission.mode": { params: PermissionConfigureParams; result: Empty; execution: "command"; permission: "trusted-client-mode"; sensitive: false }; - "permission.rules": { params: EmptyParams; result: PermissionRulesResult; execution: "query"; permission: "root-association"; sensitive: false }; - "provider.catalogs": { params: ProviderCatalogParams; result: ProviderCatalogsResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "question.answer": { params: QuestionAnswerParams; result: Empty; execution: "command"; permission: "pending-question"; sensitive: false }; - "run.configure": { params: RunConfigureParams; result: Empty; execution: "command"; permission: "root-idle"; sensitive: false }; - "schedule.create": { params: ScheduleCreateParams; result: ScheduleResult; execution: "command"; permission: "schedule-budget"; sensitive: false }; - "schedule.delete": { params: ScheduleDeleteParams; result: ScheduleResult; execution: "command"; permission: "root-association"; sensitive: false }; - "schedule.list": { params: EmptyParams; result: ScheduleListResult; execution: "query"; permission: "root-association"; sensitive: false }; - "session.archive": { params: ArchiveParams; result: ArchiveResult; execution: "command"; permission: "root-association"; sensitive: false }; - "session.create": { params: CreateSessionParams; result: RootIDResult; execution: "command"; permission: "host-runtime"; sensitive: false }; - "session.delete": { params: RootParams; result: RootIDResult; execution: "command"; permission: "root-association"; sensitive: false }; - "session.effort": { params: EffortParams; result: EffortResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "session.effort.get": { params: EmptyParams; result: EffortResult; execution: "query"; permission: "root-association"; sensitive: false }; - "session.fork": { params: ForkParams; result: RootIDResult; execution: "command"; permission: "root-association"; sensitive: false }; - "session.list": { params: ListParams; result: SessionListResult; execution: "query"; permission: "host-runtime"; sensitive: false }; - "session.model": { params: ModelParams; result: ModelResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "session.model.get": { params: EmptyParams; result: ModelResult; execution: "query"; permission: "root-association"; sensitive: false }; - "session.open": { params: IDParams; result: RootIDResult; execution: "query"; permission: "root-association"; sensitive: false }; - "session.preview": { params: IDParams; result: SessionPreviewResult; execution: "query"; permission: "root-association"; sensitive: false }; - "session.reload": { params: EmptyParams; result: ModelResult; execution: "command"; permission: "root-idle"; sensitive: false }; - "session.rename": { params: TitleParams; result: TitleResult; execution: "command"; permission: "root-association"; sensitive: false }; - "shell.run": { params: ShellParams; result: TextResult; execution: "command"; permission: "tool-permissions"; sensitive: false }; - "steer": { params: SubmitPayload; result: TextResult; execution: "command"; permission: "root-admission"; sensitive: false }; - "submit": { params: SubmitPayload; result: TextResult; execution: "command"; permission: "root-admission"; sensitive: false }; - "terminal.input": { params: TerminalInputParams; result: Empty; execution: "ephemeral"; permission: "active-terminal"; sensitive: true }; - "tool.call": { params: ToolCallParams; result: TextResult; execution: "command"; permission: "tool-permissions"; sensitive: false }; - "tool.configure": { params: ToolConfigureParams; result: Empty; execution: "command"; permission: "tool-permissions"; sensitive: false }; - "tool.schema": { params: EmptyParams; result: ToolSchemaResult; execution: "query"; permission: "tool-authority"; sensitive: false }; - "workspace.inspect": { params: EmptyParams; result: PathResult; execution: "query"; permission: "root-association"; sensitive: false }; - "workspace.set": { params: PathParams; result: PathResult; execution: "command"; permission: "workspace-authority"; sensitive: false }; -} - -export type RpcMethod = keyof RpcMethods; -export type RuntimeOperation = keyof RuntimeOperations; -export type RuntimeOperationOf<E extends RuntimeOperations[RuntimeOperation]['execution']> = { - [K in RuntimeOperation]: RuntimeOperations[K]['execution'] extends E ? K : never -}[RuntimeOperation]; -export type QueryOperation = RuntimeOperationOf<'query'>; -export type CommandOperation = RuntimeOperationOf<'command'>; -export type EphemeralOperation = RuntimeOperationOf<'ephemeral'>; -export interface OperationMetadata { - readonly name: string; - readonly surface: 'rpc' | 'runtime'; - readonly execution: 'query' | 'command' | 'ephemeral' | 'subscription' | 'lifecycle'; - readonly permission: string; - readonly sensitive: boolean; - readonly params_type: keyof ContractTypes; - readonly result_type: keyof ContractTypes; -} -export declare const rpcOperations: Readonly<{ [K in RpcMethod]: OperationMetadata & { readonly name: K; readonly execution: RpcMethods[K]['execution']; readonly permission: RpcMethods[K]['permission']; readonly sensitive: RpcMethods[K]['sensitive'] } }>; -export declare const runtimeOperations: Readonly<{ [K in RuntimeOperation]: OperationMetadata & { readonly name: K; readonly execution: RuntimeOperations[K]['execution']; readonly permission: RuntimeOperations[K]['permission']; readonly sensitive: RuntimeOperations[K]['sensitive'] } }>; -export type RootEventEnvelope = Omit<EventNotification['event'], 'kind' | 'payload'>; -export type TypedRootEvent = { [K in keyof EventPayloadTypes]: RootEventEnvelope & { unknown?: false; kind: K; payload: EventPayloadTypes[K] } }[keyof EventPayloadTypes]; -export type UnknownRootEvent = RootEventEnvelope & { unknown: true; kind: string; payload: unknown }; -export type RootEvent = TypedRootEvent | UnknownRootEvent; -export type TypedEventNotification = { event: RootEvent }; -export type ValidationMode = 'request' | 'response'; -export declare function validate<T extends keyof ContractTypes>(type: T, value: unknown, mode?: ValidationMode): value is ContractTypes[T]; -export declare function assertValid<T extends keyof ContractTypes>(type: T, value: unknown, mode?: ValidationMode): asserts value is ContractTypes[T]; -export declare const manifest: { - major: number; minor: number; - operations: readonly (Omit<OperationMetadata, 'sensitive'> & { readonly sensitive?: boolean })[]; - events: Readonly<Record<string, keyof ContractTypes>>; - event_payloads: Readonly<Record<string, keyof ContractTypes>>; -}; diff --git a/packages/protocol/generated/index.js b/packages/protocol/generated/index.js deleted file mode 100644 index 550bfcd77..000000000 --- a/packages/protocol/generated/index.js +++ /dev/null @@ -1,1306 +0,0 @@ -// Generated from Go wire types. Run npm run generate. -import * as requests from './request-validators.js'; -import * as responses from './response-validators.js'; -export const manifest = { - "major": 6, - "minor": 9, - "operations": [ - { - "name": "browser.command.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserCommandResultParams", - "result_type": "Accepted" - }, - { - "name": "browser.inventory.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserInventoryResultParams", - "result_type": "Accepted" - }, - { - "name": "browser.provider.bind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderBindParams", - "result_type": "BrowserProviderBindResult" - }, - { - "name": "browser.provider.event", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderEventParams", - "result_type": "Accepted" - }, - { - "name": "browser.provider.unbind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderUnbindParams", - "result_type": "Accepted" - }, - { - "name": "command.status", - "surface": "rpc", - "execution": "query", - "permission": "client-command-namespace", - "params_type": "CommandStatusParams", - "result_type": "CommandResult" - }, - { - "name": "command.submit", - "surface": "rpc", - "execution": "command", - "permission": "operation-specific", - "params_type": "CommandParams", - "result_type": "CommandResult" - }, - { - "name": "config.get", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "RuntimeConfiguration" - }, - { - "name": "config.update", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ConfigurationUpdate", - "result_type": "RuntimeConfiguration" - }, - { - "name": "content.read", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-content-grant", - "params_type": "ContentReadParams", - "result_type": "ContentReadResult" - }, - { - "name": "daemon.ping", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "PingResult" - }, - { - "name": "daemon.restart", - "surface": "rpc", - "execution": "lifecycle", - "permission": "armed-generation", - "params_type": "RestartParams", - "result_type": "Empty" - }, - { - "name": "daemon.stop", - "surface": "rpc", - "execution": "lifecycle", - "permission": "armed-generation", - "params_type": "RestartParams", - "result_type": "Empty" - }, - { - "name": "definitions.get", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "DefinitionParams", - "result_type": "DefinitionRecord" - }, - { - "name": "definitions.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "Empty", - "result_type": "DefinitionList" - }, - { - "name": "definitions.register", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-runtime", - "params_type": "DefinitionRegisterParams", - "result_type": "DefinitionRegisterResult" - }, - { - "name": "events.replay", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "ReplayParams", - "result_type": "ReplayResult" - }, - { - "name": "events.subscribe", - "surface": "rpc", - "execution": "subscription", - "permission": "root-association", - "params_type": "SubscribeParams", - "result_type": "SubscribeResult" - }, - { - "name": "events.unsubscribe", - "surface": "rpc", - "execution": "subscription", - "permission": "connection-subscription", - "params_type": "UnsubscribeParams", - "result_type": "Empty" - }, - { - "name": "executor.bind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-runtime", - "params_type": "ExecutorBindParams", - "result_type": "ExecutorBindResult" - }, - { - "name": "executor.pending", - "surface": "rpc", - "execution": "query", - "permission": "executor-lease", - "params_type": "ExecutorPendingParams", - "result_type": "ExecutorPendingResult" - }, - { - "name": "gateway.status", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "GatewayStatus" - }, - { - "name": "history.page", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "HistoryPageParams", - "result_type": "BoundedTranscriptPage" - }, - { - "name": "hook.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "HookResultParams", - "result_type": "Accepted" - }, - { - "name": "host.attention", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostAttentionParams", - "result_type": "HostAttentionResult" - }, - { - "name": "host.directories.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostDirectoryParams", - "result_type": "HostDirectoryResult" - }, - { - "name": "host.directory.pick", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostDirectoryPickParams", - "result_type": "HostDirectoryPickResult" - }, - { - "name": "host.skills.complete", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostSkillCompletionParams", - "result_type": "CompletionResult" - }, - { - "name": "host.themes.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "EmptyParams", - "result_type": "CatalogResult" - }, - { - "name": "host.themes.resolve", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostThemeResolveParams", - "result_type": "Resolved" - }, - { - "name": "initialize", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "InitializeParams", - "result_type": "InitializeResult" - }, - { - "name": "mailbox.list", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "MailboxPageParams", - "result_type": "MailboxPage" - }, - { - "name": "mailbox.read", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "MailboxReadParams", - "result_type": "MailboxInspection" - }, - { - "name": "mcp.brand.icons", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "MCPBrandIconsParams", - "result_type": "MCPBrandIconsResult" - }, - { - "name": "mcp.import.apply", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "MCPImportApplyParams", - "result_type": "MCPImportApplyResult" - }, - { - "name": "mcp.import.candidates", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "MCPImportCandidatesParams", - "result_type": "MCPImportCandidatesResult" - }, - { - "name": "operation.invoke", - "surface": "rpc", - "execution": "ephemeral", - "permission": "operation-specific", - "sensitive": true, - "params_type": "QueryParams", - "result_type": "QueryResult" - }, - { - "name": "permission.decide", - "surface": "rpc", - "execution": "ephemeral", - "permission": "trusted-client-decision", - "params_type": "PermissionDecisionParams", - "result_type": "PermissionDecisionResult" - }, - { - "name": "provider.create", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderCreateParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.disconnect", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ProviderDisconnectParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.discover", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderListParams", - "result_type": "ProviderList" - }, - { - "name": "provider.get", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.key.rotate", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "sensitive": true, - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.key.set", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderKeySetup", - "result_type": "RuntimeConfiguration" - }, - { - "name": "provider.list", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderListParams", - "result_type": "ProviderList" - }, - { - "name": "provider.login.begin", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginBeginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.cancel", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.list", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "Empty", - "result_type": "ProviderLoginList" - }, - { - "name": "provider.login.project.create", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginCreateParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.project.select", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginProjectParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.status", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "ProviderLoginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.team.select", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginTeamParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.logout", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.remove", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ProviderRemoveParams", - "result_type": "ProviderRemoveResult" - }, - { - "name": "provider.status", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.update", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderUpdateParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.validate", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "sensitive": true, - "params_type": "ProviderValidateParams", - "result_type": "ProviderValidateResult" - }, - { - "name": "query", - "surface": "rpc", - "execution": "query", - "permission": "operation-specific", - "params_type": "QueryParams", - "result_type": "QueryResult" - }, - { - "name": "root.collection", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "RootCollectionParams", - "result_type": "RootCollectionPage" - }, - { - "name": "root.snapshot", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "SnapshotParams", - "result_type": "RootSnapshot" - }, - { - "name": "sessions.get", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "RootParams", - "result_type": "SessionMetadata" - }, - { - "name": "sessions.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "SessionCatalogParams", - "result_type": "SessionCatalogPage" - }, - { - "name": "sessions.revision", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "EmptyParams", - "result_type": "CatalogRevision" - }, - { - "name": "sessions.summaries", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "SessionSummariesParams", - "result_type": "SessionSummariesResult" - }, - { - "name": "terminal.attach", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalAttachParams", - "result_type": "TerminalAttachResult" - }, - { - "name": "terminal.close", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalIDParams", - "result_type": "Accepted" - }, - { - "name": "terminal.open", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalOpenParams", - "result_type": "TerminalOpenResult" - }, - { - "name": "terminal.resize", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalResizeParams", - "result_type": "Accepted" - }, - { - "name": "terminal.write", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "sensitive": true, - "params_type": "TerminalWriteParams", - "result_type": "Accepted" - }, - { - "name": "tool.progress", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "ToolProgressParams", - "result_type": "Accepted" - }, - { - "name": "tool.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "ToolResultParams", - "result_type": "Accepted" - }, - { - "name": "trace.export", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "TraceExportParams", - "result_type": "TraceExportResult" - }, - { - "name": "trace.page", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "TracePageParams", - "result_type": "SpanPage" - }, - { - "name": "upload.begin", - "surface": "rpc", - "execution": "ephemeral", - "permission": "content-grant", - "params_type": "UploadBeginParams", - "result_type": "Accepted" - }, - { - "name": "upload.chunk", - "surface": "rpc", - "execution": "ephemeral", - "permission": "connection-upload", - "params_type": "UploadChunkParams", - "result_type": "Accepted" - }, - { - "name": "upload.finish", - "surface": "rpc", - "execution": "ephemeral", - "permission": "content-grant", - "params_type": "UploadFinishParams", - "result_type": "ContentHandle" - }, - { - "name": "workspace.complete", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "CompletionParams", - "result_type": "CompletionResult" - }, - { - "name": "agent.control", - "surface": "runtime", - "execution": "command", - "permission": "agent-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "agent.delete", - "surface": "runtime", - "execution": "command", - "permission": "agent-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "agent.submit", - "surface": "runtime", - "execution": "command", - "permission": "agent-admission", - "params_type": "AgentInputParams", - "result_type": "AgentSubmitResult" - }, - { - "name": "agent.transcript", - "surface": "runtime", - "execution": "query", - "permission": "human-transcript-inspection", - "params_type": "IDParams", - "result_type": "AgentTranscriptResult" - }, - { - "name": "agent.turn.cancel", - "surface": "runtime", - "execution": "command", - "permission": "target-turn", - "params_type": "AgentCancelParams", - "result_type": "Empty" - }, - { - "name": "agents.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "AgentListResult" - }, - { - "name": "browser.set_driver", - "surface": "runtime", - "execution": "command", - "permission": "host-configuration", - "params_type": "BrowserDriverParams", - "result_type": "BrowserStatusResult" - }, - { - "name": "browser.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "BrowserStatusResult" - }, - { - "name": "budget.cap", - "surface": "runtime", - "execution": "command", - "permission": "budget-authority", - "params_type": "BudgetCapParams", - "result_type": "BudgetState" - }, - { - "name": "cancel", - "surface": "runtime", - "execution": "command", - "permission": "target-turn", - "params_type": "CancelParams", - "result_type": "Empty" - }, - { - "name": "capability.revoke", - "surface": "runtime", - "execution": "command", - "permission": "capability-authority", - "params_type": "IDParams", - "result_type": "CapabilityRecord" - }, - { - "name": "compaction.configure", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "CompactionParams", - "result_type": "CompactionSettingsResult" - }, - { - "name": "computer.allow", - "surface": "runtime", - "execution": "command", - "permission": "human-computer-policy", - "params_type": "ComputerAppParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "computer.deny", - "surface": "runtime", - "execution": "command", - "permission": "human-computer-policy", - "params_type": "ComputerAppParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "computer.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "context.audit", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ContextAuditResult" - }, - { - "name": "daemon.checkpoint", - "surface": "runtime", - "execution": "command", - "permission": "host-runtime", - "params_type": "CheckpointParams", - "result_type": "RestartNotice" - }, - { - "name": "goal.from-context", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "GoalContextParams", - "result_type": "GoalResult" - }, - { - "name": "goal.run", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "TextParams", - "result_type": "GoalResult" - }, - { - "name": "goal.set", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "TextParams", - "result_type": "GoalResult" - }, - { - "name": "history.clear", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "ClearHistoryParams", - "result_type": "Empty" - }, - { - "name": "history.compact", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "CompactionResult" - }, - { - "name": "history.compact.log", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "CompactionListResult" - }, - { - "name": "history.compact.retry", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "CompactionRetryResult" - }, - { - "name": "history.rewind", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "RewindParams", - "result_type": "RewindResult" - }, - { - "name": "history.user.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "UserHistoryResult" - }, - { - "name": "inbox.remove", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "InboxRemoveParams", - "result_type": "InboxControlResult" - }, - { - "name": "inbox.steer", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "InboxSteerParams", - "result_type": "InboxControlResult" - }, - { - "name": "lsp.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "LSPListResult" - }, - { - "name": "mcp.attach", - "surface": "runtime", - "execution": "ephemeral", - "permission": "delegated-mcp-authority", - "sensitive": true, - "params_type": "MCPAttachParams", - "result_type": "Empty" - }, - { - "name": "mcp.disable", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.enable", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.import.configure", - "surface": "runtime", - "execution": "command", - "permission": "host-configuration", - "params_type": "MCPImportParams", - "result_type": "MCPImportStatusResult" - }, - { - "name": "mcp.import.status", - "surface": "runtime", - "execution": "query", - "permission": "host-configuration", - "params_type": "EmptyParams", - "result_type": "MCPImportStatusResult" - }, - { - "name": "mcp.reconnect", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.refresh", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "MCPRefreshResult" - }, - { - "name": "mcp.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "MCPListResult" - }, - { - "name": "permission.forget", - "surface": "runtime", - "execution": "command", - "permission": "rule-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "permission.mode", - "surface": "runtime", - "execution": "command", - "permission": "trusted-client-mode", - "params_type": "PermissionConfigureParams", - "result_type": "Empty" - }, - { - "name": "permission.rules", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "PermissionRulesResult" - }, - { - "name": "provider.catalogs", - "surface": "runtime", - "execution": "query", - "permission": "host-runtime", - "params_type": "ProviderCatalogParams", - "result_type": "ProviderCatalogsResult" - }, - { - "name": "question.answer", - "surface": "runtime", - "execution": "command", - "permission": "pending-question", - "params_type": "QuestionAnswerParams", - "result_type": "Empty" - }, - { - "name": "run.configure", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "RunConfigureParams", - "result_type": "Empty" - }, - { - "name": "schedule.create", - "surface": "runtime", - "execution": "command", - "permission": "schedule-budget", - "params_type": "ScheduleCreateParams", - "result_type": "ScheduleResult" - }, - { - "name": "schedule.delete", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ScheduleDeleteParams", - "result_type": "ScheduleResult" - }, - { - "name": "schedule.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ScheduleListResult" - }, - { - "name": "session.archive", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ArchiveParams", - "result_type": "ArchiveResult" - }, - { - "name": "session.create", - "surface": "runtime", - "execution": "command", - "permission": "host-runtime", - "params_type": "CreateSessionParams", - "result_type": "RootIDResult" - }, - { - "name": "session.delete", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "RootParams", - "result_type": "RootIDResult" - }, - { - "name": "session.effort", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EffortParams", - "result_type": "EffortResult" - }, - { - "name": "session.effort.get", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "EffortResult" - }, - { - "name": "session.fork", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ForkParams", - "result_type": "RootIDResult" - }, - { - "name": "session.list", - "surface": "runtime", - "execution": "query", - "permission": "host-runtime", - "params_type": "ListParams", - "result_type": "SessionListResult" - }, - { - "name": "session.model", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "ModelParams", - "result_type": "ModelResult" - }, - { - "name": "session.model.get", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ModelResult" - }, - { - "name": "session.open", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "IDParams", - "result_type": "RootIDResult" - }, - { - "name": "session.preview", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "IDParams", - "result_type": "SessionPreviewResult" - }, - { - "name": "session.reload", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "ModelResult" - }, - { - "name": "session.rename", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "TitleParams", - "result_type": "TitleResult" - }, - { - "name": "shell.run", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ShellParams", - "result_type": "TextResult" - }, - { - "name": "steer", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "SubmitPayload", - "result_type": "TextResult" - }, - { - "name": "submit", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "SubmitPayload", - "result_type": "TextResult" - }, - { - "name": "terminal.input", - "surface": "runtime", - "execution": "ephemeral", - "permission": "active-terminal", - "sensitive": true, - "params_type": "TerminalInputParams", - "result_type": "Empty" - }, - { - "name": "tool.call", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ToolCallParams", - "result_type": "TextResult" - }, - { - "name": "tool.configure", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ToolConfigureParams", - "result_type": "Empty" - }, - { - "name": "tool.schema", - "surface": "runtime", - "execution": "query", - "permission": "tool-authority", - "params_type": "EmptyParams", - "result_type": "ToolSchemaResult" - }, - { - "name": "workspace.inspect", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "PathResult" - }, - { - "name": "workspace.set", - "surface": "runtime", - "execution": "command", - "permission": "workspace-authority", - "params_type": "PathParams", - "result_type": "PathResult" - } - ], - "events": { - "browser.command": "BrowserCommand", - "browser.command.cancel": "BrowserCommandCancel", - "browser.inventory": "BrowserInventoryRequest", - "browser.provider.revoked": "BrowserProviderRevoked", - "event": "EventNotification", - "hook.cancel": "ToolCancelParams", - "hook.invoke": "HookInvokeParams", - "sessions.title.changed": "SessionTitleChangedParams", - "subscription.failed": "SubscriptionFailure", - "terminal.detached": "TerminalDetachedParams", - "terminal.exited": "TerminalExitedParams", - "terminal.output": "TerminalOutputParams", - "tool.cancel": "ToolCancelParams", - "tool.invoke": "ToolInvokeParams" - }, - "event_payloads": { - "agent.admitted": "LifecycleEvent", - "agent.prompt.queued": "LifecycleEvent", - "agent.subtree.deleted": "LifecycleEvent", - "agent.subtree.stopped": "LifecycleEvent", - "agent.turn.cancelled": "LifecycleEvent", - "agent.turn.failed": "LifecycleEvent", - "agent.turn.interrupted": "LifecycleEvent", - "agent.turn.started": "LifecycleEvent", - "agent.turn.succeeded": "LifecycleEvent", - "blackboard.append": "LifecycleEvent", - "blackboard.cas": "LifecycleEvent", - "blackboard.set": "LifecycleEvent", - "budget.active_child.reserved": "LifecycleEvent", - "budget.capped": "LifecycleEvent", - "capability.delegated": "LifecycleEvent", - "capability.revoked": "LifecycleEvent", - "command.cancelled": "LifecycleEvent", - "command.control.queued": "LifecycleEvent", - "command.failed": "LifecycleEvent", - "command.interrupted": "LifecycleEvent", - "command.queued": "LifecycleEvent", - "command.running": "LifecycleEvent", - "command.succeeded": "LifecycleEvent", - "command.waiting": "LifecycleEvent", - "goal.continued": "LifecycleEvent", - "inbox.consumed": "LifecycleEvent", - "inbox.failed": "LifecycleEvent", - "inbox.queued": "LifecycleEvent", - "inbox.removed": "LifecycleEvent", - "inbox.running": "LifecycleEvent", - "inbox.steering": "LifecycleEvent", - "message.deferred": "LifecycleEvent", - "message.delivered": "LifecycleEvent", - "message.done": "LifecycleEvent", - "message.queued": "LifecycleEvent", - "message.updated": "LifecycleEvent", - "model.call.corrected": "LifecycleEvent", - "model.call.interrupted": "LifecycleEvent", - "model.call.settled": "LifecycleEvent", - "model.call.started": "LifecycleEvent", - "permission.auto_approved": "LifecycleEvent", - "permission.pending": "LifecycleEvent", - "question.answered": "LifecycleEvent", - "question.closed": "LifecycleEvent", - "question.pending": "LifecycleEvent", - "root.failed": "LifecycleEvent", - "root.interrupted": "LifecycleEvent", - "root.stopped": "LifecycleEvent", - "schedule.fired": "LifecycleEvent", - "scratch.restored": "LifecycleEvent", - "session.archived.updated": "SessionUpdateEvent", - "session.cwd.updated": "SessionUpdateEvent", - "session.effort.updated": "SessionUpdateEvent", - "session.model.updated": "SessionUpdateEvent", - "session.permission_mode.updated": "SessionUpdateEvent", - "session.reload.failed": "LifecycleEvent", - "session.title.updated": "SessionUpdateEvent", - "span.ended": "SpanRecord", - "span.started": "SpanRecord", - "state.private.append": "LifecycleEvent", - "state.private.cas": "LifecycleEvent", - "state.private.set": "LifecycleEvent", - "stream.accounting": "StreamEvent", - "stream.cell.host": "StreamEvent", - "stream.cell.host.started": "StreamEvent", - "stream.discard": "StreamEvent", - "stream.hook.decision": "StreamEvent", - "stream.notice": "StreamEvent", - "stream.reasoning": "StreamEvent", - "stream.terminal.awaiting": "StreamEvent", - "stream.terminal.completed": "StreamEvent", - "stream.terminal.output": "StreamEvent", - "stream.terminal.started": "StreamEvent", - "stream.text": "StreamEvent", - "stream.tool.call": "StreamEvent", - "stream.tool.completed": "StreamEvent", - "stream.tool.output": "StreamEvent", - "stream.tool.progress": "StreamEvent", - "stream.tool.started": "StreamEvent", - "stream.usage": "StreamEvent", - "subscription.cancelled": "LifecycleEvent", - "subscription.created": "LifecycleEvent", - "turn.cancelled": "LifecycleEvent", - "turn.failed": "LifecycleEvent", - "turn.interrupted": "LifecycleEvent", - "turn.started": "LifecycleEvent", - "turn.succeeded": "LifecycleEvent" - } -}; -function operationLookup(surface) { - return Object.freeze(Object.fromEntries(manifest.operations.filter(operation => operation.surface === surface).map(operation => - [operation.name, Object.freeze({ ...operation, sensitive: operation.sensitive ?? false })], - ))); -} -export const rpcOperations = operationLookup('rpc'); -export const runtimeOperations = operationLookup('runtime'); -function validatorFor(type, mode) { - if (mode !== 'request' && mode !== 'response') throw new TypeError('Unknown WHIP validation mode: ' + mode); - const validators = mode === 'response' ? responses : requests; - if (!Object.hasOwn(validators, type)) throw new TypeError('Unknown WHIP contract type: ' + type); - return validators[type]; -} -export function validate(type, value, mode = 'request') { - return validatorFor(type, mode)(value); -} -export function assertValid(type, value, mode = 'request') { - const validator = validatorFor(type, mode); - if (!validator(value)) { - const details = validator.errors.map(error => (error.instancePath || '/') + ' ' + error.message).join('; '); - throw new TypeError('Invalid WHIP ' + type + ': ' + details); - } -} diff --git a/packages/protocol/generated/request-validators.js b/packages/protocol/generated/request-validators.js deleted file mode 100644 index 6f5b37a19..000000000 --- a/packages/protocol/generated/request-validators.js +++ /dev/null @@ -1,73085 +0,0 @@ -// Generated standalone validators. Run npm run generate. -"use strict"; -export const Accepted = validate10; -const schema11 = {"type":"object","properties":{"accepted":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/Accepted","$schema":"http://json-schema.org/draft-07/schema#","title":"Accepted","required":["accepted"],"additionalProperties":false}; - -function validate10(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Accepted" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.accepted === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "accepted"},message:"must have required property '"+"accepted"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "accepted")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.accepted !== undefined){ -if(typeof data.accepted !== "boolean"){ -const err2 = {instancePath:instancePath+"/accepted",schemaPath:"#/properties/accepted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate10.errors = vErrors; -return errors === 0; -} - -export const AgentCancelParams = validate11; -const schema12 = {"type":"object","properties":{"id":{"type":"string"},"turn_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/AgentCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentCancelParams","required":["id","turn_id"],"additionalProperties":false}; - -function validate11(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentCancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.turn_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "turn_id"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err4 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate11.errors = vErrors; -return errors === 0; -} - -export const AgentInputParams = validate12; -const schema13 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"id":{"type":"string"},"text":{"type":"string"},"delivery":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/AgentInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentInputParams","required":["id","text"],"additionalProperties":false}; -const formats0 = {int64: {type: 'string', validate: value => { - if (!/^-?(0|[1-9][0-9]*)$/.test(value) || value.length > 20) return false; - const number = BigInt(value); - return number >= -9223372036854775808n && number <= 9223372036854775807n; -}}}.int64; -const pattern0 = new RegExp("^-?(0|[1-9][0-9]*)$", "u"); - -function validate12(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentInputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.text === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "design_context") || (key0 === "id")) || (key0 === "text")) || (key0 === "delivery")) || (key0 === "parts")) || (key0 === "attachments"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.design_context !== undefined){ -let data0 = data.design_context; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema13.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.context_attachment_id === undefined){ -const err4 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.elements === undefined){ -const err5 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.element_count === undefined){ -const err6 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key1 in data0){ -if(!((((((key1 === "context_attachment_id") || (key1 === "screenshot_attachment_id")) || (key1 === "elements")) || (key1 === "element_count")) || (key1 === "page_url")) || (key1 === "page_title"))){ -const err7 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.context_attachment_id !== undefined){ -if(typeof data0.context_attachment_id !== "string"){ -const err8 = {instancePath:instancePath+"/design_context/context_attachment_id",schemaPath:"#/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.screenshot_attachment_id !== undefined){ -if(typeof data0.screenshot_attachment_id !== "string"){ -const err9 = {instancePath:instancePath+"/design_context/screenshot_attachment_id",schemaPath:"#/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.elements !== undefined){ -let data3 = data0.elements; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err10 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema13.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.label === undefined){ -const err11 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -for(const key2 in data4){ -if(!((key2 === "label") || (key2 === "selector"))){ -const err12 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.label !== undefined){ -if(typeof data4.label !== "string"){ -const err13 = {instancePath:instancePath+"/design_context/elements/" + i0+"/label",schemaPath:"#/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data4.selector !== undefined){ -if(typeof data4.selector !== "string"){ -const err14 = {instancePath:instancePath+"/design_context/elements/" + i0+"/selector",schemaPath:"#/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data0.element_count !== undefined){ -let data7 = data0.element_count; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err16 = {instancePath:instancePath+"/design_context/element_count",schemaPath:"#/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data0.page_url !== undefined){ -if(typeof data0.page_url !== "string"){ -const err17 = {instancePath:instancePath+"/design_context/page_url",schemaPath:"#/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.page_title !== undefined){ -if(typeof data0.page_title !== "string"){ -const err18 = {instancePath:instancePath+"/design_context/page_title",schemaPath:"#/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err19 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err20 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err21 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.parts !== undefined){ -let data13 = data.parts; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err22 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema13.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data13)){ -const len1 = data13.length; -for(let i1=0; i1<len1; i1++){ -let data14 = data13[i1]; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.type === undefined){ -const err23 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -for(const key3 in data14){ -if(!(((((key3 === "type") || (key3 === "text")) || (key3 === "image_url")) || (key3 === "w")) || (key3 === "h"))){ -const err24 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data14.type !== undefined){ -if(typeof data14.type !== "string"){ -const err25 = {instancePath:instancePath+"/parts/" + i1+"/type",schemaPath:"#/properties/parts/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data14.text !== undefined){ -if(typeof data14.text !== "string"){ -const err26 = {instancePath:instancePath+"/parts/" + i1+"/text",schemaPath:"#/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data14.image_url !== undefined){ -let data17 = data14.image_url; -if((data17 !== null) && (!(data17 && typeof data17 == "object" && !Array.isArray(data17)))){ -const err27 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema13.properties.parts.items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.url === undefined){ -const err28 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -for(const key4 in data17){ -if(!(key4 === "url")){ -const err29 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data17.url !== undefined){ -if(typeof data17.url !== "string"){ -const err30 = {instancePath:instancePath+"/parts/" + i1+"/image_url/url",schemaPath:"#/properties/parts/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -} -if(data14.w !== undefined){ -let data19 = data14.w; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err31 = {instancePath:instancePath+"/parts/" + i1+"/w",schemaPath:"#/properties/parts/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data14.h !== undefined){ -let data20 = data14.h; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err32 = {instancePath:instancePath+"/parts/" + i1+"/h",schemaPath:"#/properties/parts/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -if(data.attachments !== undefined){ -let data21 = data.attachments; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err34 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema13.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(Array.isArray(data21)){ -const len2 = data21.length; -for(let i2=0; i2<len2; i2++){ -let data22 = data21[i2]; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.kind === undefined){ -const err35 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data22.content === undefined){ -const err36 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -for(const key5 in data22){ -if(!(((key5 === "kind") || (key5 === "content")) || (key5 === "name"))){ -const err37 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data22.kind !== undefined){ -let data23 = data22.kind; -if(typeof data23 !== "string"){ -const err38 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(!((data23 === "image") || (data23 === "text"))){ -const err39 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema13.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data22.content !== undefined){ -let data24 = data22.content; -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.reference_id === undefined){ -const err40 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data24.digest === undefined){ -const err41 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data24.size === undefined){ -const err42 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -for(const key6 in data24){ -if(!(((((key6 === "reference_id") || (key6 === "digest")) || (key6 === "size")) || (key6 === "media_type")) || (key6 === "source"))){ -const err43 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data24.reference_id !== undefined){ -if(typeof data24.reference_id !== "string"){ -const err44 = {instancePath:instancePath+"/attachments/" + i2+"/content/reference_id",schemaPath:"#/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data24.digest !== undefined){ -if(typeof data24.digest !== "string"){ -const err45 = {instancePath:instancePath+"/attachments/" + i2+"/content/digest",schemaPath:"#/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data24.size !== undefined){ -let data27 = data24.size; -if(typeof data27 === "string"){ -if(!pattern0.test(data27)){ -const err46 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(!(formats0.validate(data27))){ -const err47 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -else { -const err48 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data24.media_type !== undefined){ -if(typeof data24.media_type !== "string"){ -const err49 = {instancePath:instancePath+"/attachments/" + i2+"/content/media_type",schemaPath:"#/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data24.source !== undefined){ -if(typeof data24.source !== "string"){ -const err50 = {instancePath:instancePath+"/attachments/" + i2+"/content/source",schemaPath:"#/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -else { -const err51 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data22.name !== undefined){ -if(typeof data22.name !== "string"){ -const err52 = {instancePath:instancePath+"/attachments/" + i2+"/name",schemaPath:"#/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -} -else { -const err53 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -} -} -} -else { -const err54 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -validate12.errors = vErrors; -return errors === 0; -} - -export const AgentListResult = validate13; -const schema14 = {"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":false},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/AgentListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentListResult"}; -const func2 = Object.prototype.hasOwnProperty; - -function validate13(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema14.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.execution_engine === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.id === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.root_id === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.parent_id === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.name === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.model === undefined){ -const err6 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.provider === undefined){ -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.effort === undefined){ -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.cwd === undefined){ -const err9 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.report === undefined){ -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.status === undefined){ -const err11 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.pending_mail === undefined){ -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.lifecycle_phase === undefined){ -const err13 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.blocking_reason === undefined){ -const err14 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.terminal_cause === undefined){ -const err15 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.allowed_controls === undefined){ -const err16 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -for(const key0 in data0){ -if(!(func2.call(schema14.items.properties, key0))){ -const err17 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.execution_engine !== undefined){ -if(typeof data0.execution_engine !== "string"){ -const err18 = {instancePath:instancePath+"/" + i0+"/execution_engine",schemaPath:"#/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data0.last_turn !== undefined){ -let data2 = data0.last_turn; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err19 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/type",keyword:"type",params:{type: schema14.items.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.status === undefined){ -const err20 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.event_seq === undefined){ -const err21 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -for(const key1 in data2){ -if(!(func2.call(schema14.items.properties.last_turn.properties, key1))){ -const err22 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.turn_id !== undefined){ -if(typeof data2.turn_id !== "string"){ -const err23 = {instancePath:instancePath+"/" + i0+"/last_turn/turn_id",schemaPath:"#/items/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err24 = {instancePath:instancePath+"/" + i0+"/last_turn/status",schemaPath:"#/items/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.started_at !== undefined){ -if(typeof data2.started_at !== "string"){ -const err25 = {instancePath:instancePath+"/" + i0+"/last_turn/started_at",schemaPath:"#/items/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.finished_at !== undefined){ -if(typeof data2.finished_at !== "string"){ -const err26 = {instancePath:instancePath+"/" + i0+"/last_turn/finished_at",schemaPath:"#/items/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.event_seq !== undefined){ -let data7 = data2.event_seq; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err27 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err28 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -else { -const err29 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data2.error !== undefined){ -if(typeof data2.error !== "string"){ -const err30 = {instancePath:instancePath+"/" + i0+"/last_turn/error",schemaPath:"#/items/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data2.error_truncated !== undefined){ -if(typeof data2.error_truncated !== "boolean"){ -const err31 = {instancePath:instancePath+"/" + i0+"/last_turn/error_truncated",schemaPath:"#/items/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data2.error_details !== undefined){ -let data10 = data2.error_details; -if((data10 !== null) && (!(data10 && typeof data10 == "object" && !Array.isArray(data10)))){ -const err32 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.reference_id === undefined){ -const err33 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data10.digest === undefined){ -const err34 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data10.size === undefined){ -const err35 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data10.media_type === undefined){ -const err36 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data10.source === undefined){ -const err37 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -for(const key2 in data10){ -if(!((((((((key2 === "inline") || (key2 === "text")) || (key2 === "binary")) || (key2 === "reference_id")) || (key2 === "digest")) || (key2 === "size")) || (key2 === "media_type")) || (key2 === "source"))){ -const err38 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data10.text !== undefined){ -let data11 = data10.text; -if((data11 !== null) && (typeof data11 !== "string")){ -const err39 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/text",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data10.binary !== undefined){ -let data12 = data10.binary; -if((typeof data12 !== "string") && (data12 !== null)){ -const err40 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/binary",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data10.reference_id !== undefined){ -if(typeof data10.reference_id !== "string"){ -const err41 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/reference_id",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data10.digest !== undefined){ -if(typeof data10.digest !== "string"){ -const err42 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/digest",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data10.size !== undefined){ -let data15 = data10.size; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err43 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err44 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data10.media_type !== undefined){ -if(typeof data10.media_type !== "string"){ -const err46 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/media_type",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data10.source !== undefined){ -if(typeof data10.source !== "string"){ -const err47 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/source",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -} -if(data2.model_calls !== undefined){ -let data18 = data2.model_calls; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err48 = {instancePath:instancePath+"/" + i0+"/last_turn/model_calls",schemaPath:"#/items/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data2.compactions !== undefined){ -let data19 = data2.compactions; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err49 = {instancePath:instancePath+"/" + i0+"/last_turn/compactions",schemaPath:"#/items/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data2.last_activity_at !== undefined){ -if(typeof data2.last_activity_at !== "string"){ -const err50 = {instancePath:instancePath+"/" + i0+"/last_turn/last_activity_at",schemaPath:"#/items/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err51 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err52 = {instancePath:instancePath+"/" + i0+"/root_id",schemaPath:"#/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data0.parent_id !== undefined){ -if(typeof data0.parent_id !== "string"){ -const err53 = {instancePath:instancePath+"/" + i0+"/parent_id",schemaPath:"#/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err54 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data0.model !== undefined){ -if(typeof data0.model !== "string"){ -const err55 = {instancePath:instancePath+"/" + i0+"/model",schemaPath:"#/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data0.provider !== undefined){ -if(typeof data0.provider !== "string"){ -const err56 = {instancePath:instancePath+"/" + i0+"/provider",schemaPath:"#/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data0.effort !== undefined){ -if(typeof data0.effort !== "string"){ -const err57 = {instancePath:instancePath+"/" + i0+"/effort",schemaPath:"#/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data0.cwd !== undefined){ -if(typeof data0.cwd !== "string"){ -const err58 = {instancePath:instancePath+"/" + i0+"/cwd",schemaPath:"#/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data0.report !== undefined){ -if(typeof data0.report !== "string"){ -const err59 = {instancePath:instancePath+"/" + i0+"/report",schemaPath:"#/items/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data0.status !== undefined){ -if(typeof data0.status !== "string"){ -const err60 = {instancePath:instancePath+"/" + i0+"/status",schemaPath:"#/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data0.pending_mail !== undefined){ -let data31 = data0.pending_mail; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err61 = {instancePath:instancePath+"/" + i0+"/pending_mail",schemaPath:"#/items/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data0.lifecycle_phase !== undefined){ -if(typeof data0.lifecycle_phase !== "string"){ -const err62 = {instancePath:instancePath+"/" + i0+"/lifecycle_phase",schemaPath:"#/items/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data0.blocking_reason !== undefined){ -if(typeof data0.blocking_reason !== "string"){ -const err63 = {instancePath:instancePath+"/" + i0+"/blocking_reason",schemaPath:"#/items/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data0.terminal_cause !== undefined){ -if(typeof data0.terminal_cause !== "string"){ -const err64 = {instancePath:instancePath+"/" + i0+"/terminal_cause",schemaPath:"#/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data0.allowed_controls !== undefined){ -let data35 = data0.allowed_controls; -if((data35 !== null) && (!(Array.isArray(data35)))){ -const err65 = {instancePath:instancePath+"/" + i0+"/allowed_controls",schemaPath:"#/items/properties/allowed_controls/type",keyword:"type",params:{type: schema14.items.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(Array.isArray(data35)){ -const len1 = data35.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data35[i1] !== "string"){ -const err66 = {instancePath:instancePath+"/" + i0+"/allowed_controls/" + i1,schemaPath:"#/items/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -} -} -} -else { -const err67 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -validate13.errors = vErrors; -return errors === 0; -} - -export const AgentSubmitResult = validate14; -const schema15 = {"type":"object","properties":{"agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/AgentSubmitResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentSubmitResult","required":["agent_id","inbox_seq","status"],"additionalProperties":false}; - -function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentSubmitResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.agent_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.status === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "agent_id") || (key0 === "inbox_seq")) || (key0 === "kind")) || (key0 === "status"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err4 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err8 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err9 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate14.errors = vErrors; -return errors === 0; -} - -export const AgentTranscriptResult = validate15; -const schema16 = {"type":"object","properties":{"accounting":{"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"agent":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":false},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":false},"page":{"type":"object","properties":{"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"through_seq":{"type":"integer"},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":false},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false}},"required":["invocation_id","name","status"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":false},"role":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"seq":{"type":"integer"},"message":{"type":["null","object"],"properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":false},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false}},"required":["invocation_id","name","status"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":false},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":false},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":false}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":false},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["seq"],"additionalProperties":false}}},"required":["history_revision","through_seq","next_seq","has_more","messages"],"additionalProperties":false},"presentation":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":false}},"inbox":{"type":["null","array"],"items":{"type":"object","properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["kind","content"],"additionalProperties":false}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":false},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/AgentTranscriptResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentTranscriptResult","required":["cursor","agent","page"],"additionalProperties":false}; - -function validate15(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentTranscriptResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cursor === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent"},message:"must have required property '"+"agent"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.page === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "page"},message:"must have required property '"+"page"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "accounting") || (key0 === "cursor")) || (key0 === "agent")) || (key0 === "page")) || (key0 === "presentation")) || (key0 === "inbox"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.accounting !== undefined){ -let data0 = data.accounting; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.root_id === undefined){ -const err4 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.agent_id === undefined){ -const err5 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.scope === undefined){ -const err6 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.revision === undefined){ -const err7 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.reported_cost_micros === undefined){ -const err8 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.estimated_cost_micros === undefined){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.reported_cost_calls === undefined){ -const err10 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.estimated_cost_calls === undefined){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.unknown_cost_calls === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.reported_calls === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.estimated_calls === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.pending_calls === undefined){ -const err15 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -for(const key1 in data0){ -if(!(func2.call(schema16.properties.accounting.properties, key1))){ -const err16 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err17 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.agent_id !== undefined){ -if(typeof data0.agent_id !== "string"){ -const err18 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data0.scope !== undefined){ -if(typeof data0.scope !== "string"){ -const err19 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data0.revision !== undefined){ -let data4 = data0.revision; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err20 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err21 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -else { -const err22 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data0.reported_cost_micros !== undefined){ -let data5 = data0.reported_cost_micros; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err23 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err24 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data0.estimated_cost_micros !== undefined){ -let data6 = data0.estimated_cost_micros; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err26 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err27 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data0.reported_cost_calls !== undefined){ -let data7 = data0.reported_cost_calls; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err29 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err30 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data0.estimated_cost_calls !== undefined){ -let data8 = data0.estimated_cost_calls; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err32 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err33 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -else { -const err34 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data0.unknown_cost_calls !== undefined){ -let data9 = data0.unknown_cost_calls; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err35 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err36 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -else { -const err37 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data0.reported_calls !== undefined){ -let data10 = data0.reported_calls; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err38 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err39 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -else { -const err40 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data0.estimated_calls !== undefined){ -let data11 = data0.estimated_calls; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err41 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err42 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -else { -const err43 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data0.pending_calls !== undefined){ -let data12 = data0.pending_calls; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err44 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err45 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -else { -const err46 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -else { -const err47 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data13 = data.cursor; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err48 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err49 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -else { -const err50 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data.agent !== undefined){ -let data14 = data.agent; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.execution_engine === undefined){ -const err51 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data14.id === undefined){ -const err52 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data14.root_id === undefined){ -const err53 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data14.parent_id === undefined){ -const err54 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data14.name === undefined){ -const err55 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data14.model === undefined){ -const err56 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data14.provider === undefined){ -const err57 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data14.effort === undefined){ -const err58 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data14.cwd === undefined){ -const err59 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data14.report === undefined){ -const err60 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data14.status === undefined){ -const err61 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data14.pending_mail === undefined){ -const err62 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data14.lifecycle_phase === undefined){ -const err63 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data14.blocking_reason === undefined){ -const err64 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data14.terminal_cause === undefined){ -const err65 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data14.allowed_controls === undefined){ -const err66 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -for(const key2 in data14){ -if(!(func2.call(schema16.properties.agent.properties, key2))){ -const err67 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data14.execution_engine !== undefined){ -if(typeof data14.execution_engine !== "string"){ -const err68 = {instancePath:instancePath+"/agent/execution_engine",schemaPath:"#/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data14.last_turn !== undefined){ -let data16 = data14.last_turn; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err69 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.status === undefined){ -const err70 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data16.event_seq === undefined){ -const err71 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -for(const key3 in data16){ -if(!(func2.call(schema16.properties.agent.properties.last_turn.properties, key3))){ -const err72 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data16.turn_id !== undefined){ -if(typeof data16.turn_id !== "string"){ -const err73 = {instancePath:instancePath+"/agent/last_turn/turn_id",schemaPath:"#/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data16.status !== undefined){ -if(typeof data16.status !== "string"){ -const err74 = {instancePath:instancePath+"/agent/last_turn/status",schemaPath:"#/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data16.started_at !== undefined){ -if(typeof data16.started_at !== "string"){ -const err75 = {instancePath:instancePath+"/agent/last_turn/started_at",schemaPath:"#/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data16.finished_at !== undefined){ -if(typeof data16.finished_at !== "string"){ -const err76 = {instancePath:instancePath+"/agent/last_turn/finished_at",schemaPath:"#/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data16.event_seq !== undefined){ -let data21 = data16.event_seq; -if(typeof data21 === "string"){ -if(!pattern0.test(data21)){ -const err77 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(!(formats0.validate(data21))){ -const err78 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -else { -const err79 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data16.error !== undefined){ -if(typeof data16.error !== "string"){ -const err80 = {instancePath:instancePath+"/agent/last_turn/error",schemaPath:"#/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data16.error_truncated !== undefined){ -if(typeof data16.error_truncated !== "boolean"){ -const err81 = {instancePath:instancePath+"/agent/last_turn/error_truncated",schemaPath:"#/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data16.error_details !== undefined){ -let data24 = data16.error_details; -if((data24 !== null) && (!(data24 && typeof data24 == "object" && !Array.isArray(data24)))){ -const err82 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.reference_id === undefined){ -const err83 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data24.digest === undefined){ -const err84 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data24.size === undefined){ -const err85 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data24.media_type === undefined){ -const err86 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data24.source === undefined){ -const err87 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -for(const key4 in data24){ -if(!((((((((key4 === "inline") || (key4 === "text")) || (key4 === "binary")) || (key4 === "reference_id")) || (key4 === "digest")) || (key4 === "size")) || (key4 === "media_type")) || (key4 === "source"))){ -const err88 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data24.text !== undefined){ -let data25 = data24.text; -if((data25 !== null) && (typeof data25 !== "string")){ -const err89 = {instancePath:instancePath+"/agent/last_turn/error_details/text",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data24.binary !== undefined){ -let data26 = data24.binary; -if((typeof data26 !== "string") && (data26 !== null)){ -const err90 = {instancePath:instancePath+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data24.reference_id !== undefined){ -if(typeof data24.reference_id !== "string"){ -const err91 = {instancePath:instancePath+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data24.digest !== undefined){ -if(typeof data24.digest !== "string"){ -const err92 = {instancePath:instancePath+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data24.size !== undefined){ -let data29 = data24.size; -if(typeof data29 === "string"){ -if(!pattern0.test(data29)){ -const err93 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(!(formats0.validate(data29))){ -const err94 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -else { -const err95 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data24.media_type !== undefined){ -if(typeof data24.media_type !== "string"){ -const err96 = {instancePath:instancePath+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data24.source !== undefined){ -if(typeof data24.source !== "string"){ -const err97 = {instancePath:instancePath+"/agent/last_turn/error_details/source",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -} -if(data16.model_calls !== undefined){ -let data32 = data16.model_calls; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err98 = {instancePath:instancePath+"/agent/last_turn/model_calls",schemaPath:"#/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data16.compactions !== undefined){ -let data33 = data16.compactions; -if(!((typeof data33 == "number") && (!(data33 % 1) && !isNaN(data33)))){ -const err99 = {instancePath:instancePath+"/agent/last_turn/compactions",schemaPath:"#/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data16.last_activity_at !== undefined){ -if(typeof data16.last_activity_at !== "string"){ -const err100 = {instancePath:instancePath+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -} -} -if(data14.id !== undefined){ -if(typeof data14.id !== "string"){ -const err101 = {instancePath:instancePath+"/agent/id",schemaPath:"#/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data14.root_id !== undefined){ -if(typeof data14.root_id !== "string"){ -const err102 = {instancePath:instancePath+"/agent/root_id",schemaPath:"#/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data14.parent_id !== undefined){ -if(typeof data14.parent_id !== "string"){ -const err103 = {instancePath:instancePath+"/agent/parent_id",schemaPath:"#/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data14.name !== undefined){ -if(typeof data14.name !== "string"){ -const err104 = {instancePath:instancePath+"/agent/name",schemaPath:"#/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data14.model !== undefined){ -if(typeof data14.model !== "string"){ -const err105 = {instancePath:instancePath+"/agent/model",schemaPath:"#/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data14.provider !== undefined){ -if(typeof data14.provider !== "string"){ -const err106 = {instancePath:instancePath+"/agent/provider",schemaPath:"#/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data14.effort !== undefined){ -if(typeof data14.effort !== "string"){ -const err107 = {instancePath:instancePath+"/agent/effort",schemaPath:"#/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data14.cwd !== undefined){ -if(typeof data14.cwd !== "string"){ -const err108 = {instancePath:instancePath+"/agent/cwd",schemaPath:"#/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data14.report !== undefined){ -if(typeof data14.report !== "string"){ -const err109 = {instancePath:instancePath+"/agent/report",schemaPath:"#/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data14.status !== undefined){ -if(typeof data14.status !== "string"){ -const err110 = {instancePath:instancePath+"/agent/status",schemaPath:"#/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data14.pending_mail !== undefined){ -let data45 = data14.pending_mail; -if(!((typeof data45 == "number") && (!(data45 % 1) && !isNaN(data45)))){ -const err111 = {instancePath:instancePath+"/agent/pending_mail",schemaPath:"#/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data14.lifecycle_phase !== undefined){ -if(typeof data14.lifecycle_phase !== "string"){ -const err112 = {instancePath:instancePath+"/agent/lifecycle_phase",schemaPath:"#/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data14.blocking_reason !== undefined){ -if(typeof data14.blocking_reason !== "string"){ -const err113 = {instancePath:instancePath+"/agent/blocking_reason",schemaPath:"#/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data14.terminal_cause !== undefined){ -if(typeof data14.terminal_cause !== "string"){ -const err114 = {instancePath:instancePath+"/agent/terminal_cause",schemaPath:"#/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data14.allowed_controls !== undefined){ -let data49 = data14.allowed_controls; -if((data49 !== null) && (!(Array.isArray(data49)))){ -const err115 = {instancePath:instancePath+"/agent/allowed_controls",schemaPath:"#/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema16.properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -if(Array.isArray(data49)){ -const len0 = data49.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data49[i0] !== "string"){ -const err116 = {instancePath:instancePath+"/agent/allowed_controls/" + i0,schemaPath:"#/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -} -} -} -else { -const err117 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -if(data.page !== undefined){ -let data51 = data.page; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.history_revision === undefined){ -const err118 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data51.through_seq === undefined){ -const err119 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data51.next_seq === undefined){ -const err120 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(data51.has_more === undefined){ -const err121 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data51.messages === undefined){ -const err122 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -for(const key5 in data51){ -if(!(((((key5 === "history_revision") || (key5 === "through_seq")) || (key5 === "next_seq")) || (key5 === "has_more")) || (key5 === "messages"))){ -const err123 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data51.history_revision !== undefined){ -let data52 = data51.history_revision; -if(typeof data52 === "string"){ -if(!pattern0.test(data52)){ -const err124 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -if(!(formats0.validate(data52))){ -const err125 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -else { -const err126 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -if(data51.through_seq !== undefined){ -let data53 = data51.through_seq; -if(!((typeof data53 == "number") && (!(data53 % 1) && !isNaN(data53)))){ -const err127 = {instancePath:instancePath+"/page/through_seq",schemaPath:"#/properties/page/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data51.next_seq !== undefined){ -let data54 = data51.next_seq; -if(!((typeof data54 == "number") && (!(data54 % 1) && !isNaN(data54)))){ -const err128 = {instancePath:instancePath+"/page/next_seq",schemaPath:"#/properties/page/properties/next_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data51.has_more !== undefined){ -if(typeof data51.has_more !== "boolean"){ -const err129 = {instancePath:instancePath+"/page/has_more",schemaPath:"#/properties/page/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -if(data51.messages !== undefined){ -let data56 = data51.messages; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err130 = {instancePath:instancePath+"/page/messages",schemaPath:"#/properties/page/properties/messages/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -if(Array.isArray(data56)){ -const len1 = data56.length; -for(let i1=0; i1<len1; i1++){ -let data57 = data56[i1]; -if(data57 && typeof data57 == "object" && !Array.isArray(data57)){ -if(data57.seq === undefined){ -const err131 = {instancePath:instancePath+"/page/messages/" + i1,schemaPath:"#/properties/page/properties/messages/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -for(const key6 in data57){ -if(!(((((((key6 === "presentation") || (key6 === "role")) || (key6 === "authored")) || (key6 === "sent_at")) || (key6 === "seq")) || (key6 === "message")) || (key6 === "body"))){ -const err132 = {instancePath:instancePath+"/page/messages/" + i1,schemaPath:"#/properties/page/properties/messages/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data57.presentation !== undefined){ -let data58 = data57.presentation; -if((data58 !== null) && (!(data58 && typeof data58 == "object" && !Array.isArray(data58)))){ -const err133 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -if(data58 && typeof data58 == "object" && !Array.isArray(data58)){ -if(data58.version === undefined){ -const err134 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -for(const key7 in data58){ -if(!(((((key7 === "design_context") || (key7 === "version")) || (key7 === "turn_id")) || (key7 === "parts")) || (key7 === "omitted"))){ -const err135 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -if(data58.design_context !== undefined){ -let data59 = data58.design_context; -if((data59 !== null) && (!(data59 && typeof data59 == "object" && !Array.isArray(data59)))){ -const err136 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -if(data59 && typeof data59 == "object" && !Array.isArray(data59)){ -if(data59.context_attachment_id === undefined){ -const err137 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -if(data59.elements === undefined){ -const err138 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -if(data59.element_count === undefined){ -const err139 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -if(data59.context_part_index === undefined){ -const err140 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -for(const key8 in data59){ -if(!((((((((key8 === "context_attachment_id") || (key8 === "screenshot_attachment_id")) || (key8 === "elements")) || (key8 === "element_count")) || (key8 === "page_url")) || (key8 === "page_title")) || (key8 === "context_part_index")) || (key8 === "screenshot_part_index"))){ -const err141 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -if(data59.context_attachment_id !== undefined){ -if(typeof data59.context_attachment_id !== "string"){ -const err142 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data59.screenshot_attachment_id !== undefined){ -if(typeof data59.screenshot_attachment_id !== "string"){ -const err143 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data59.elements !== undefined){ -let data62 = data59.elements; -if((data62 !== null) && (!(Array.isArray(data62)))){ -const err144 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(Array.isArray(data62)){ -const len2 = data62.length; -for(let i2=0; i2<len2; i2++){ -let data63 = data62[i2]; -if(data63 && typeof data63 == "object" && !Array.isArray(data63)){ -if(data63.label === undefined){ -const err145 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -for(const key9 in data63){ -if(!((key9 === "label") || (key9 === "selector"))){ -const err146 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -if(data63.label !== undefined){ -if(typeof data63.label !== "string"){ -const err147 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2+"/label",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -if(data63.selector !== undefined){ -if(typeof data63.selector !== "string"){ -const err148 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2+"/selector",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -} -else { -const err149 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -} -} -if(data59.element_count !== undefined){ -let data66 = data59.element_count; -if(!((typeof data66 == "number") && (!(data66 % 1) && !isNaN(data66)))){ -const err150 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/element_count",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -if(data59.page_url !== undefined){ -if(typeof data59.page_url !== "string"){ -const err151 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/page_url",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data59.page_title !== undefined){ -if(typeof data59.page_title !== "string"){ -const err152 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/page_title",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data59.context_part_index !== undefined){ -let data69 = data59.context_part_index; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err153 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/context_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -if(data59.screenshot_part_index !== undefined){ -let data70 = data59.screenshot_part_index; -if((data70 !== null) && (!((typeof data70 == "number") && (!(data70 % 1) && !isNaN(data70))))){ -const err154 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -} -} -} -if(data58.version !== undefined){ -let data71 = data58.version; -if(!((typeof data71 == "number") && (!(data71 % 1) && !isNaN(data71)))){ -const err155 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/version",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -} -if(data58.turn_id !== undefined){ -if(typeof data58.turn_id !== "string"){ -const err156 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/turn_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -} -if(data58.parts !== undefined){ -let data73 = data58.parts; -if((data73 !== null) && (!(Array.isArray(data73)))){ -const err157 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -if(Array.isArray(data73)){ -const len3 = data73.length; -for(let i3=0; i3<len3; i3++){ -let data74 = data73[i3]; -if(data74 && typeof data74 == "object" && !Array.isArray(data74)){ -if(data74.id === undefined){ -const err158 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -if(data74.kind === undefined){ -const err159 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -for(const key10 in data74){ -if(!(func2.call(schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.items.properties, key10))){ -const err160 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data74.id !== undefined){ -if(typeof data74.id !== "string"){ -const err161 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -} -if(data74.kind !== undefined){ -if(typeof data74.kind !== "string"){ -const err162 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/kind",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -} -if(data74.start !== undefined){ -let data77 = data74.start; -if(!((typeof data77 == "number") && (!(data77 % 1) && !isNaN(data77)))){ -const err163 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/start",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -} -if(data74.end !== undefined){ -let data78 = data74.end; -if(!((typeof data78 == "number") && (!(data78 % 1) && !isNaN(data78)))){ -const err164 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/end",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data74.text !== undefined){ -if(typeof data74.text !== "string"){ -const err165 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -if(data74.tool_name !== undefined){ -if(typeof data74.tool_name !== "string"){ -const err166 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/tool_name",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -if(data74.status !== undefined){ -if(typeof data74.status !== "string"){ -const err167 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -if(data74.call_id !== undefined){ -if(typeof data74.call_id !== "string"){ -const err168 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -} -if(data74.hosts !== undefined){ -let data83 = data74.hosts; -if((data83 !== null) && (!(Array.isArray(data83)))){ -const err169 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -if(Array.isArray(data83)){ -const len4 = data83.length; -for(let i4=0; i4<len4; i4++){ -let data84 = data83[i4]; -if(data84 && typeof data84 == "object" && !Array.isArray(data84)){ -if(data84.invocation_id === undefined){ -const err170 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -if(data84.name === undefined){ -const err171 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -if(data84.status === undefined){ -const err172 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -for(const key11 in data84){ -if(!(((((((key11 === "invocation_id") || (key11 === "name")) || (key11 === "summary")) || (key11 === "status")) || (key11 === "duration")) || (key11 === "error")) || (key11 === "display"))){ -const err173 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -if(data84.invocation_id !== undefined){ -if(typeof data84.invocation_id !== "string"){ -const err174 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/invocation_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -} -if(data84.name !== undefined){ -if(typeof data84.name !== "string"){ -const err175 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/name",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -} -if(data84.summary !== undefined){ -if(typeof data84.summary !== "string"){ -const err176 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/summary",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -} -if(data84.status !== undefined){ -if(typeof data84.status !== "string"){ -const err177 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -if(data84.duration !== undefined){ -if(typeof data84.duration !== "string"){ -const err178 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/duration",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -if(data84.error !== undefined){ -if(typeof data84.error !== "string"){ -const err179 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/error",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -if(data84.display !== undefined){ -let data91 = data84.display; -if((data91 !== null) && (!(data91 && typeof data91 == "object" && !Array.isArray(data91)))){ -const err180 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -if(data91 && typeof data91 == "object" && !Array.isArray(data91)){ -for(const key12 in data91){ -if(!(((((key12 === "target") || (key12 === "command")) || (key12 === "query")) || (key12 === "child_id")) || (key12 === "label"))){ -const err181 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -} -if(data91.target !== undefined){ -if(typeof data91.target !== "string"){ -const err182 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/target",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -} -if(data91.command !== undefined){ -if(typeof data91.command !== "string"){ -const err183 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/command",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -} -if(data91.query !== undefined){ -if(typeof data91.query !== "string"){ -const err184 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/query",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -} -if(data91.child_id !== undefined){ -if(typeof data91.child_id !== "string"){ -const err185 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/child_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -if(data91.label !== undefined){ -if(typeof data91.label !== "string"){ -const err186 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/label",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -} -} -} -} -else { -const err187 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -} -} -} -if(data74.omitted !== undefined){ -let data97 = data74.omitted; -if(!((typeof data97 == "number") && (!(data97 % 1) && !isNaN(data97)))){ -const err188 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -} -} -else { -const err189 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -} -} -} -if(data58.omitted !== undefined){ -let data98 = data58.omitted; -if(!((typeof data98 == "number") && (!(data98 % 1) && !isNaN(data98)))){ -const err190 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -} -} -} -if(data57.role !== undefined){ -if(typeof data57.role !== "string"){ -const err191 = {instancePath:instancePath+"/page/messages/" + i1+"/role",schemaPath:"#/properties/page/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -} -if(data57.authored !== undefined){ -if(typeof data57.authored !== "boolean"){ -const err192 = {instancePath:instancePath+"/page/messages/" + i1+"/authored",schemaPath:"#/properties/page/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -} -if(data57.sent_at !== undefined){ -let data101 = data57.sent_at; -if((data101 !== null) && (typeof data101 !== "string")){ -const err193 = {instancePath:instancePath+"/page/messages/" + i1+"/sent_at",schemaPath:"#/properties/page/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -} -if(data57.seq !== undefined){ -let data102 = data57.seq; -if(!((typeof data102 == "number") && (!(data102 % 1) && !isNaN(data102)))){ -const err194 = {instancePath:instancePath+"/page/messages/" + i1+"/seq",schemaPath:"#/properties/page/properties/messages/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -} -if(data57.message !== undefined){ -let data103 = data57.message; -if((data103 !== null) && (!(data103 && typeof data103 == "object" && !Array.isArray(data103)))){ -const err195 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.role === undefined){ -const err196 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -if(data103.content === undefined){ -const err197 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -for(const key13 in data103){ -if(!(func2.call(schema16.properties.page.properties.messages.items.properties.message.properties, key13))){ -const err198 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -} -if(data103.presentation !== undefined){ -let data104 = data103.presentation; -if((data104 !== null) && (!(data104 && typeof data104 == "object" && !Array.isArray(data104)))){ -const err199 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -if(data104 && typeof data104 == "object" && !Array.isArray(data104)){ -if(data104.version === undefined){ -const err200 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -for(const key14 in data104){ -if(!(((((key14 === "design_context") || (key14 === "version")) || (key14 === "turn_id")) || (key14 === "parts")) || (key14 === "omitted"))){ -const err201 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -} -if(data104.design_context !== undefined){ -let data105 = data104.design_context; -if((data105 !== null) && (!(data105 && typeof data105 == "object" && !Array.isArray(data105)))){ -const err202 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -if(data105 && typeof data105 == "object" && !Array.isArray(data105)){ -if(data105.context_attachment_id === undefined){ -const err203 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -if(data105.elements === undefined){ -const err204 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -if(data105.element_count === undefined){ -const err205 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -if(data105.context_part_index === undefined){ -const err206 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -for(const key15 in data105){ -if(!((((((((key15 === "context_attachment_id") || (key15 === "screenshot_attachment_id")) || (key15 === "elements")) || (key15 === "element_count")) || (key15 === "page_url")) || (key15 === "page_title")) || (key15 === "context_part_index")) || (key15 === "screenshot_part_index"))){ -const err207 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -} -if(data105.context_attachment_id !== undefined){ -if(typeof data105.context_attachment_id !== "string"){ -const err208 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/context_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -} -if(data105.screenshot_attachment_id !== undefined){ -if(typeof data105.screenshot_attachment_id !== "string"){ -const err209 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -} -if(data105.elements !== undefined){ -let data108 = data105.elements; -if((data108 !== null) && (!(Array.isArray(data108)))){ -const err210 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -if(Array.isArray(data108)){ -const len5 = data108.length; -for(let i5=0; i5<len5; i5++){ -let data109 = data108[i5]; -if(data109 && typeof data109 == "object" && !Array.isArray(data109)){ -if(data109.label === undefined){ -const err211 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -for(const key16 in data109){ -if(!((key16 === "label") || (key16 === "selector"))){ -const err212 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -} -if(data109.label !== undefined){ -if(typeof data109.label !== "string"){ -const err213 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5+"/label",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -} -if(data109.selector !== undefined){ -if(typeof data109.selector !== "string"){ -const err214 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5+"/selector",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -} -} -else { -const err215 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -} -} -} -if(data105.element_count !== undefined){ -let data112 = data105.element_count; -if(!((typeof data112 == "number") && (!(data112 % 1) && !isNaN(data112)))){ -const err216 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/element_count",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -} -if(data105.page_url !== undefined){ -if(typeof data105.page_url !== "string"){ -const err217 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/page_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -} -if(data105.page_title !== undefined){ -if(typeof data105.page_title !== "string"){ -const err218 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/page_title",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -} -if(data105.context_part_index !== undefined){ -let data115 = data105.context_part_index; -if(!((typeof data115 == "number") && (!(data115 % 1) && !isNaN(data115)))){ -const err219 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/context_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -} -if(data105.screenshot_part_index !== undefined){ -let data116 = data105.screenshot_part_index; -if((data116 !== null) && (!((typeof data116 == "number") && (!(data116 % 1) && !isNaN(data116))))){ -const err220 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -} -} -} -if(data104.version !== undefined){ -let data117 = data104.version; -if(!((typeof data117 == "number") && (!(data117 % 1) && !isNaN(data117)))){ -const err221 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/version",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -} -if(data104.turn_id !== undefined){ -if(typeof data104.turn_id !== "string"){ -const err222 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/turn_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -} -if(data104.parts !== undefined){ -let data119 = data104.parts; -if((data119 !== null) && (!(Array.isArray(data119)))){ -const err223 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -if(Array.isArray(data119)){ -const len6 = data119.length; -for(let i6=0; i6<len6; i6++){ -let data120 = data119[i6]; -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.id === undefined){ -const err224 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -if(data120.kind === undefined){ -const err225 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -for(const key17 in data120){ -if(!(func2.call(schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties, key17))){ -const err226 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key17},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -} -if(data120.id !== undefined){ -if(typeof data120.id !== "string"){ -const err227 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -} -if(data120.kind !== undefined){ -if(typeof data120.kind !== "string"){ -const err228 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/kind",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -} -if(data120.start !== undefined){ -let data123 = data120.start; -if(!((typeof data123 == "number") && (!(data123 % 1) && !isNaN(data123)))){ -const err229 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/start",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -} -if(data120.end !== undefined){ -let data124 = data120.end; -if(!((typeof data124 == "number") && (!(data124 % 1) && !isNaN(data124)))){ -const err230 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/end",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -} -if(data120.text !== undefined){ -if(typeof data120.text !== "string"){ -const err231 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -} -if(data120.tool_name !== undefined){ -if(typeof data120.tool_name !== "string"){ -const err232 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/tool_name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -} -if(data120.status !== undefined){ -if(typeof data120.status !== "string"){ -const err233 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -} -if(data120.call_id !== undefined){ -if(typeof data120.call_id !== "string"){ -const err234 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -} -if(data120.hosts !== undefined){ -let data129 = data120.hosts; -if((data129 !== null) && (!(Array.isArray(data129)))){ -const err235 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -if(Array.isArray(data129)){ -const len7 = data129.length; -for(let i7=0; i7<len7; i7++){ -let data130 = data129[i7]; -if(data130 && typeof data130 == "object" && !Array.isArray(data130)){ -if(data130.invocation_id === undefined){ -const err236 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -if(data130.name === undefined){ -const err237 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -if(data130.status === undefined){ -const err238 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -for(const key18 in data130){ -if(!(((((((key18 === "invocation_id") || (key18 === "name")) || (key18 === "summary")) || (key18 === "status")) || (key18 === "duration")) || (key18 === "error")) || (key18 === "display"))){ -const err239 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key18},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -} -if(data130.invocation_id !== undefined){ -if(typeof data130.invocation_id !== "string"){ -const err240 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/invocation_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data130.name !== undefined){ -if(typeof data130.name !== "string"){ -const err241 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data130.summary !== undefined){ -if(typeof data130.summary !== "string"){ -const err242 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/summary",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -} -if(data130.status !== undefined){ -if(typeof data130.status !== "string"){ -const err243 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -} -if(data130.duration !== undefined){ -if(typeof data130.duration !== "string"){ -const err244 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/duration",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -} -if(data130.error !== undefined){ -if(typeof data130.error !== "string"){ -const err245 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/error",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -} -if(data130.display !== undefined){ -let data137 = data130.display; -if((data137 !== null) && (!(data137 && typeof data137 == "object" && !Array.isArray(data137)))){ -const err246 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -if(data137 && typeof data137 == "object" && !Array.isArray(data137)){ -for(const key19 in data137){ -if(!(((((key19 === "target") || (key19 === "command")) || (key19 === "query")) || (key19 === "child_id")) || (key19 === "label"))){ -const err247 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key19},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -} -if(data137.target !== undefined){ -if(typeof data137.target !== "string"){ -const err248 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/target",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -} -if(data137.command !== undefined){ -if(typeof data137.command !== "string"){ -const err249 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/command",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -} -if(data137.query !== undefined){ -if(typeof data137.query !== "string"){ -const err250 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/query",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -} -if(data137.child_id !== undefined){ -if(typeof data137.child_id !== "string"){ -const err251 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/child_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -} -if(data137.label !== undefined){ -if(typeof data137.label !== "string"){ -const err252 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/label",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -} -} -} -} -else { -const err253 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -} -} -} -if(data120.omitted !== undefined){ -let data143 = data120.omitted; -if(!((typeof data143 == "number") && (!(data143 % 1) && !isNaN(data143)))){ -const err254 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -} -} -else { -const err255 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -} -} -} -if(data104.omitted !== undefined){ -let data144 = data104.omitted; -if(!((typeof data144 == "number") && (!(data144 % 1) && !isNaN(data144)))){ -const err256 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -} -} -} -if(data103.role !== undefined){ -if(typeof data103.role !== "string"){ -const err257 = {instancePath:instancePath+"/page/messages/" + i1+"/message/role",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -} -if(data103.content !== undefined){ -let data146 = data103.content; -const _errs314 = errors; -let valid36 = false; -const _errs315 = errors; -if(typeof data146 !== "string"){ -const err258 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -var _valid0 = _errs315 === errors; -valid36 = valid36 || _valid0; -if(!valid36){ -const _errs317 = errors; -if(Array.isArray(data146)){ -const len8 = data146.length; -for(let i8=0; i8<len8; i8++){ -let data147 = data146[i8]; -if(data147 && typeof data147 == "object" && !Array.isArray(data147)){ -if(data147.type === undefined){ -const err259 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -for(const key20 in data147){ -if(!(((((key20 === "type") || (key20 === "text")) || (key20 === "image_url")) || (key20 === "w")) || (key20 === "h"))){ -const err260 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key20},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -} -if(data147.type !== undefined){ -if(typeof data147.type !== "string"){ -const err261 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/type",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -} -if(data147.text !== undefined){ -if(typeof data147.text !== "string"){ -const err262 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -} -if(data147.image_url !== undefined){ -let data150 = data147.image_url; -if((data150 !== null) && (!(data150 && typeof data150 == "object" && !Array.isArray(data150)))){ -const err263 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -if(data150 && typeof data150 == "object" && !Array.isArray(data150)){ -if(data150.url === undefined){ -const err264 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -for(const key21 in data150){ -if(!(key21 === "url")){ -const err265 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key21},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -} -if(data150.url !== undefined){ -if(typeof data150.url !== "string"){ -const err266 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url/url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -} -} -} -if(data147.w !== undefined){ -let data152 = data147.w; -if(!((typeof data152 == "number") && (!(data152 % 1) && !isNaN(data152)))){ -const err267 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/w",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -} -if(data147.h !== undefined){ -let data153 = data147.h; -if(!((typeof data153 == "number") && (!(data153 % 1) && !isNaN(data153)))){ -const err268 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/h",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -} -} -else { -const err269 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -} -} -else { -const err270 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -var _valid0 = _errs317 === errors; -valid36 = valid36 || _valid0; -} -if(!valid36){ -const err271 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -else { -errors = _errs314; -if(vErrors !== null){ -if(_errs314){ -vErrors.length = _errs314; -} -else { -vErrors = null; -} -} -} -} -if(data103.tool_calls !== undefined){ -let data154 = data103.tool_calls; -if((data154 !== null) && (!(Array.isArray(data154)))){ -const err272 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -if(Array.isArray(data154)){ -const len9 = data154.length; -for(let i9=0; i9<len9; i9++){ -let data155 = data154[i9]; -if(data155 && typeof data155 == "object" && !Array.isArray(data155)){ -if(data155.id === undefined){ -const err273 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -if(data155.type === undefined){ -const err274 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -if(data155.function === undefined){ -const err275 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -for(const key22 in data155){ -if(!(((((key22 === "id") || (key22 === "type")) || (key22 === "function")) || (key22 === "duration_ms")) || (key22 === "exit_code"))){ -const err276 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key22},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -} -if(data155.id !== undefined){ -if(typeof data155.id !== "string"){ -const err277 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -} -if(data155.type !== undefined){ -if(typeof data155.type !== "string"){ -const err278 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/type",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -} -if(data155.function !== undefined){ -let data158 = data155.function; -if(data158 && typeof data158 == "object" && !Array.isArray(data158)){ -if(data158.name === undefined){ -const err279 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -if(data158.arguments === undefined){ -const err280 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -for(const key23 in data158){ -if(!((key23 === "name") || (key23 === "arguments"))){ -const err281 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key23},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -} -if(data158.name !== undefined){ -if(typeof data158.name !== "string"){ -const err282 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -} -if(data158.arguments !== undefined){ -if(typeof data158.arguments !== "string"){ -const err283 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function/arguments",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -} -} -else { -const err284 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -} -if(data155.duration_ms !== undefined){ -let data161 = data155.duration_ms; -if(!((typeof data161 == "number") && (!(data161 % 1) && !isNaN(data161)))){ -const err285 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/duration_ms",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -} -if(data155.exit_code !== undefined){ -let data162 = data155.exit_code; -if(!((typeof data162 == "number") && (!(data162 % 1) && !isNaN(data162)))){ -const err286 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/exit_code",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -} -} -else { -const err287 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -} -} -} -if(data103.tool_call_id !== undefined){ -if(typeof data103.tool_call_id !== "string"){ -const err288 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -} -if(data103.name !== undefined){ -if(typeof data103.name !== "string"){ -const err289 = {instancePath:instancePath+"/page/messages/" + i1+"/message/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -} -if(data103.authored !== undefined){ -if(typeof data103.authored !== "boolean"){ -const err290 = {instancePath:instancePath+"/page/messages/" + i1+"/message/authored",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -} -if(data103.sent_at !== undefined){ -let data166 = data103.sent_at; -if((data166 !== null) && (typeof data166 !== "string")){ -const err291 = {instancePath:instancePath+"/page/messages/" + i1+"/message/sent_at",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/sent_at/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data103.usage !== undefined){ -let data167 = data103.usage; -if((data167 !== null) && (!(data167 && typeof data167 == "object" && !Array.isArray(data167)))){ -const err292 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -if(data167 && typeof data167 == "object" && !Array.isArray(data167)){ -if(data167.prompt_tokens === undefined){ -const err293 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -if(data167.completion_tokens === undefined){ -const err294 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -for(const key24 in data167){ -if(!((((((key24 === "reported") || (key24 === "cost")) || (key24 === "prompt_tokens")) || (key24 === "completion_tokens")) || (key24 === "prompt_tokens_details")) || (key24 === "completion_tokens_details"))){ -const err295 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key24},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -} -if(data167.reported !== undefined){ -if(typeof data167.reported !== "boolean"){ -const err296 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/reported",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -} -if(data167.cost !== undefined){ -let data169 = data167.cost; -if((data169 !== null) && (!(typeof data169 == "number"))){ -const err297 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/cost",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/cost/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -} -if(data167.prompt_tokens !== undefined){ -let data170 = data167.prompt_tokens; -if(!((typeof data170 == "number") && (!(data170 % 1) && !isNaN(data170)))){ -const err298 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -} -if(data167.completion_tokens !== undefined){ -let data171 = data167.completion_tokens; -if(!((typeof data171 == "number") && (!(data171 % 1) && !isNaN(data171)))){ -const err299 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -} -if(data167.prompt_tokens_details !== undefined){ -let data172 = data167.prompt_tokens_details; -if((data172 !== null) && (!(data172 && typeof data172 == "object" && !Array.isArray(data172)))){ -const err300 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -if(data172 && typeof data172 == "object" && !Array.isArray(data172)){ -if(data172.cached_tokens === undefined){ -const err301 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -for(const key25 in data172){ -if(!(key25 === "cached_tokens")){ -const err302 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key25},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -} -if(data172.cached_tokens !== undefined){ -let data173 = data172.cached_tokens; -if(!((typeof data173 == "number") && (!(data173 % 1) && !isNaN(data173)))){ -const err303 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -} -} -} -if(data167.completion_tokens_details !== undefined){ -let data174 = data167.completion_tokens_details; -if((data174 !== null) && (!(data174 && typeof data174 == "object" && !Array.isArray(data174)))){ -const err304 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -if(data174 && typeof data174 == "object" && !Array.isArray(data174)){ -if(data174.reasoning_tokens === undefined){ -const err305 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -for(const key26 in data174){ -if(!(key26 === "reasoning_tokens")){ -const err306 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key26},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -} -if(data174.reasoning_tokens !== undefined){ -let data175 = data174.reasoning_tokens; -if(!((typeof data175 == "number") && (!(data175 % 1) && !isNaN(data175)))){ -const err307 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -} -} -} -} -} -if(data103.model !== undefined){ -if(typeof data103.model !== "string"){ -const err308 = {instancePath:instancePath+"/page/messages/" + i1+"/message/model",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -} -if(data103.rewound_from !== undefined){ -if(typeof data103.rewound_from !== "string"){ -const err309 = {instancePath:instancePath+"/page/messages/" + i1+"/message/rewound_from",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -} -if(data103.call_id !== undefined){ -if(typeof data103.call_id !== "string"){ -const err310 = {instancePath:instancePath+"/page/messages/" + i1+"/message/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -} -} -} -if(data57.body !== undefined){ -let data179 = data57.body; -if((data179 !== null) && (!(data179 && typeof data179 == "object" && !Array.isArray(data179)))){ -const err311 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -if(data179 && typeof data179 == "object" && !Array.isArray(data179)){ -if(data179.reference_id === undefined){ -const err312 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -if(data179.digest === undefined){ -const err313 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -if(data179.size === undefined){ -const err314 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -if(data179.media_type === undefined){ -const err315 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -if(data179.source === undefined){ -const err316 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -for(const key27 in data179){ -if(!((((((((key27 === "inline") || (key27 === "text")) || (key27 === "binary")) || (key27 === "reference_id")) || (key27 === "digest")) || (key27 === "size")) || (key27 === "media_type")) || (key27 === "source"))){ -const err317 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key27},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -} -if(data179.text !== undefined){ -let data180 = data179.text; -if((data180 !== null) && (typeof data180 !== "string")){ -const err318 = {instancePath:instancePath+"/page/messages/" + i1+"/body/text",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/text/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -} -if(data179.binary !== undefined){ -let data181 = data179.binary; -if((typeof data181 !== "string") && (data181 !== null)){ -const err319 = {instancePath:instancePath+"/page/messages/" + i1+"/body/binary",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -} -if(data179.reference_id !== undefined){ -if(typeof data179.reference_id !== "string"){ -const err320 = {instancePath:instancePath+"/page/messages/" + i1+"/body/reference_id",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -} -if(data179.digest !== undefined){ -if(typeof data179.digest !== "string"){ -const err321 = {instancePath:instancePath+"/page/messages/" + i1+"/body/digest",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -} -if(data179.size !== undefined){ -let data184 = data179.size; -if(typeof data184 === "string"){ -if(!pattern0.test(data184)){ -const err322 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -if(!(formats0.validate(data184))){ -const err323 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -} -else { -const err324 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -} -if(data179.media_type !== undefined){ -if(typeof data179.media_type !== "string"){ -const err325 = {instancePath:instancePath+"/page/messages/" + i1+"/body/media_type",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -} -if(data179.source !== undefined){ -if(typeof data179.source !== "string"){ -const err326 = {instancePath:instancePath+"/page/messages/" + i1+"/body/source",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -} -} -} -} -else { -const err327 = {instancePath:instancePath+"/page/messages/" + i1,schemaPath:"#/properties/page/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -} -} -} -} -else { -const err328 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -} -if(data.presentation !== undefined){ -let data187 = data.presentation; -if((data187 !== null) && (!(Array.isArray(data187)))){ -const err329 = {instancePath:instancePath+"/presentation",schemaPath:"#/properties/presentation/type",keyword:"type",params:{type: schema16.properties.presentation.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -if(Array.isArray(data187)){ -const len10 = data187.length; -for(let i10=0; i10<len10; i10++){ -let data188 = data187[i10]; -if(data188 && typeof data188 == "object" && !Array.isArray(data188)){ -if(data188.seq === undefined){ -const err330 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -if(data188.kind === undefined){ -const err331 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -if(data188.payload === undefined){ -const err332 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -for(const key28 in data188){ -if(!(((key28 === "seq") || (key28 === "kind")) || (key28 === "payload"))){ -const err333 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key28},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -} -if(data188.seq !== undefined){ -let data189 = data188.seq; -if(typeof data189 === "string"){ -if(!pattern0.test(data189)){ -const err334 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -if(!(formats0.validate(data189))){ -const err335 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -else { -const err336 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -} -if(data188.kind !== undefined){ -if(typeof data188.kind !== "string"){ -const err337 = {instancePath:instancePath+"/presentation/" + i10+"/kind",schemaPath:"#/properties/presentation/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -} -} -else { -const err338 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -} -} -} -if(data.inbox !== undefined){ -let data191 = data.inbox; -if((data191 !== null) && (!(Array.isArray(data191)))){ -const err339 = {instancePath:instancePath+"/inbox",schemaPath:"#/properties/inbox/type",keyword:"type",params:{type: schema16.properties.inbox.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -if(Array.isArray(data191)){ -const len11 = data191.length; -for(let i11=0; i11<len11; i11++){ -let data192 = data191[i11]; -if(data192 && typeof data192 == "object" && !Array.isArray(data192)){ -if(data192.root_id === undefined){ -const err340 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -if(data192.agent_id === undefined){ -const err341 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -if(data192.seq === undefined){ -const err342 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -if(data192.kind === undefined){ -const err343 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -if(data192.status === undefined){ -const err344 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -if(data192.payload === undefined){ -const err345 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -for(const key29 in data192){ -if(!(func2.call(schema16.properties.inbox.items.properties, key29))){ -const err346 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key29},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -} -if(data192.delivery_seq !== undefined){ -let data193 = data192.delivery_seq; -if(typeof data193 === "string"){ -if(!pattern0.test(data193)){ -const err347 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -if(!(formats0.validate(data193))){ -const err348 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -} -else { -const err349 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -} -if(data192.origin !== undefined){ -if(typeof data192.origin !== "string"){ -const err350 = {instancePath:instancePath+"/inbox/" + i11+"/origin",schemaPath:"#/properties/inbox/items/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -} -if(data192.command_client_id !== undefined){ -if(typeof data192.command_client_id !== "string"){ -const err351 = {instancePath:instancePath+"/inbox/" + i11+"/command_client_id",schemaPath:"#/properties/inbox/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -} -if(data192.command_id !== undefined){ -if(typeof data192.command_id !== "string"){ -const err352 = {instancePath:instancePath+"/inbox/" + i11+"/command_id",schemaPath:"#/properties/inbox/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -} -if(data192.steer_turn_id !== undefined){ -if(typeof data192.steer_turn_id !== "string"){ -const err353 = {instancePath:instancePath+"/inbox/" + i11+"/steer_turn_id",schemaPath:"#/properties/inbox/items/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -} -if(data192.preview !== undefined){ -let data198 = data192.preview; -if((data198 !== null) && (!(data198 && typeof data198 == "object" && !Array.isArray(data198)))){ -const err354 = {instancePath:instancePath+"/inbox/" + i11+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -if(data198 && typeof data198 == "object" && !Array.isArray(data198)){ -if(data198.text === undefined){ -const err355 = {instancePath:instancePath+"/inbox/" + i11+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -for(const key30 in data198){ -if(!(((((key30 === "design_context") || (key30 === "text")) || (key30 === "truncated")) || (key30 === "attachments")) || (key30 === "attachment_count"))){ -const err356 = {instancePath:instancePath+"/inbox/" + i11+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key30},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -} -if(data198.design_context !== undefined){ -let data199 = data198.design_context; -if((data199 !== null) && (!(data199 && typeof data199 == "object" && !Array.isArray(data199)))){ -const err357 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -if(data199 && typeof data199 == "object" && !Array.isArray(data199)){ -if(data199.context_attachment_id === undefined){ -const err358 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -if(data199.elements === undefined){ -const err359 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -if(data199.element_count === undefined){ -const err360 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -for(const key31 in data199){ -if(!((((((key31 === "context_attachment_id") || (key31 === "screenshot_attachment_id")) || (key31 === "elements")) || (key31 === "element_count")) || (key31 === "page_url")) || (key31 === "page_title"))){ -const err361 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key31},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -} -if(data199.context_attachment_id !== undefined){ -if(typeof data199.context_attachment_id !== "string"){ -const err362 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/context_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -} -if(data199.screenshot_attachment_id !== undefined){ -if(typeof data199.screenshot_attachment_id !== "string"){ -const err363 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -} -if(data199.elements !== undefined){ -let data202 = data199.elements; -if((data202 !== null) && (!(Array.isArray(data202)))){ -const err364 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -if(Array.isArray(data202)){ -const len12 = data202.length; -for(let i12=0; i12<len12; i12++){ -let data203 = data202[i12]; -if(data203 && typeof data203 == "object" && !Array.isArray(data203)){ -if(data203.label === undefined){ -const err365 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -for(const key32 in data203){ -if(!((key32 === "label") || (key32 === "selector"))){ -const err366 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key32},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -} -if(data203.label !== undefined){ -if(typeof data203.label !== "string"){ -const err367 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12+"/label",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -} -if(data203.selector !== undefined){ -if(typeof data203.selector !== "string"){ -const err368 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12+"/selector",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -} -} -else { -const err369 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -} -} -} -if(data199.element_count !== undefined){ -let data206 = data199.element_count; -if(!((typeof data206 == "number") && (!(data206 % 1) && !isNaN(data206)))){ -const err370 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/element_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -} -if(data199.page_url !== undefined){ -if(typeof data199.page_url !== "string"){ -const err371 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/page_url",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -} -if(data199.page_title !== undefined){ -if(typeof data199.page_title !== "string"){ -const err372 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/page_title",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -} -} -} -if(data198.text !== undefined){ -if(typeof data198.text !== "string"){ -const err373 = {instancePath:instancePath+"/inbox/" + i11+"/preview/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -} -if(data198.truncated !== undefined){ -if(typeof data198.truncated !== "boolean"){ -const err374 = {instancePath:instancePath+"/inbox/" + i11+"/preview/truncated",schemaPath:"#/properties/inbox/items/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -} -if(data198.attachments !== undefined){ -let data211 = data198.attachments; -if((data211 !== null) && (!(Array.isArray(data211)))){ -const err375 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -if(Array.isArray(data211)){ -const len13 = data211.length; -for(let i13=0; i13<len13; i13++){ -let data212 = data211[i13]; -if(data212 && typeof data212 == "object" && !Array.isArray(data212)){ -if(data212.kind === undefined){ -const err376 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -if(data212.content === undefined){ -const err377 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -for(const key33 in data212){ -if(!(((key33 === "kind") || (key33 === "name")) || (key33 === "content"))){ -const err378 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key33},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -} -if(data212.kind !== undefined){ -if(typeof data212.kind !== "string"){ -const err379 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/kind",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -} -if(data212.name !== undefined){ -if(typeof data212.name !== "string"){ -const err380 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/name",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -} -if(data212.content !== undefined){ -let data215 = data212.content; -if(data215 && typeof data215 == "object" && !Array.isArray(data215)){ -if(data215.reference_id === undefined){ -const err381 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -if(data215.digest === undefined){ -const err382 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -if(data215.size === undefined){ -const err383 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -if(data215.media_type === undefined){ -const err384 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -if(data215.source === undefined){ -const err385 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -for(const key34 in data215){ -if(!((((((((key34 === "inline") || (key34 === "text")) || (key34 === "binary")) || (key34 === "reference_id")) || (key34 === "digest")) || (key34 === "size")) || (key34 === "media_type")) || (key34 === "source"))){ -const err386 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key34},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -if(data215.text !== undefined){ -let data216 = data215.text; -if((data216 !== null) && (typeof data216 !== "string")){ -const err387 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -} -if(data215.binary !== undefined){ -let data217 = data215.binary; -if((typeof data217 !== "string") && (data217 !== null)){ -const err388 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/binary",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err388]; -} -else { -vErrors.push(err388); -} -errors++; -} -} -if(data215.reference_id !== undefined){ -if(typeof data215.reference_id !== "string"){ -const err389 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/reference_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err389]; -} -else { -vErrors.push(err389); -} -errors++; -} -} -if(data215.digest !== undefined){ -if(typeof data215.digest !== "string"){ -const err390 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/digest",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err390]; -} -else { -vErrors.push(err390); -} -errors++; -} -} -if(data215.size !== undefined){ -let data220 = data215.size; -if(typeof data220 === "string"){ -if(!pattern0.test(data220)){ -const err391 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err391]; -} -else { -vErrors.push(err391); -} -errors++; -} -if(!(formats0.validate(data220))){ -const err392 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err392]; -} -else { -vErrors.push(err392); -} -errors++; -} -} -else { -const err393 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err393]; -} -else { -vErrors.push(err393); -} -errors++; -} -} -if(data215.media_type !== undefined){ -if(typeof data215.media_type !== "string"){ -const err394 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/media_type",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err394]; -} -else { -vErrors.push(err394); -} -errors++; -} -} -if(data215.source !== undefined){ -if(typeof data215.source !== "string"){ -const err395 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/source",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err395]; -} -else { -vErrors.push(err395); -} -errors++; -} -} -} -else { -const err396 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err396]; -} -else { -vErrors.push(err396); -} -errors++; -} -} -} -else { -const err397 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err397]; -} -else { -vErrors.push(err397); -} -errors++; -} -} -} -} -if(data198.attachment_count !== undefined){ -let data223 = data198.attachment_count; -if(!((typeof data223 == "number") && (!(data223 % 1) && !isNaN(data223)))){ -const err398 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachment_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err398]; -} -else { -vErrors.push(err398); -} -errors++; -} -} -} -} -if(data192.root_id !== undefined){ -if(typeof data192.root_id !== "string"){ -const err399 = {instancePath:instancePath+"/inbox/" + i11+"/root_id",schemaPath:"#/properties/inbox/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err399]; -} -else { -vErrors.push(err399); -} -errors++; -} -} -if(data192.agent_id !== undefined){ -if(typeof data192.agent_id !== "string"){ -const err400 = {instancePath:instancePath+"/inbox/" + i11+"/agent_id",schemaPath:"#/properties/inbox/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err400]; -} -else { -vErrors.push(err400); -} -errors++; -} -} -if(data192.seq !== undefined){ -let data226 = data192.seq; -if(typeof data226 === "string"){ -if(!pattern0.test(data226)){ -const err401 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err401]; -} -else { -vErrors.push(err401); -} -errors++; -} -if(!(formats0.validate(data226))){ -const err402 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err402]; -} -else { -vErrors.push(err402); -} -errors++; -} -} -else { -const err403 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err403]; -} -else { -vErrors.push(err403); -} -errors++; -} -} -if(data192.kind !== undefined){ -if(typeof data192.kind !== "string"){ -const err404 = {instancePath:instancePath+"/inbox/" + i11+"/kind",schemaPath:"#/properties/inbox/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err404]; -} -else { -vErrors.push(err404); -} -errors++; -} -} -if(data192.status !== undefined){ -if(typeof data192.status !== "string"){ -const err405 = {instancePath:instancePath+"/inbox/" + i11+"/status",schemaPath:"#/properties/inbox/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err405]; -} -else { -vErrors.push(err405); -} -errors++; -} -} -if(data192.payload !== undefined){ -let data229 = data192.payload; -if(data229 && typeof data229 == "object" && !Array.isArray(data229)){ -if(data229.reference_id === undefined){ -const err406 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err406]; -} -else { -vErrors.push(err406); -} -errors++; -} -if(data229.digest === undefined){ -const err407 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err407]; -} -else { -vErrors.push(err407); -} -errors++; -} -if(data229.size === undefined){ -const err408 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err408]; -} -else { -vErrors.push(err408); -} -errors++; -} -if(data229.media_type === undefined){ -const err409 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err409]; -} -else { -vErrors.push(err409); -} -errors++; -} -if(data229.source === undefined){ -const err410 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err410]; -} -else { -vErrors.push(err410); -} -errors++; -} -for(const key35 in data229){ -if(!((((((((key35 === "inline") || (key35 === "text")) || (key35 === "binary")) || (key35 === "reference_id")) || (key35 === "digest")) || (key35 === "size")) || (key35 === "media_type")) || (key35 === "source"))){ -const err411 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key35},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err411]; -} -else { -vErrors.push(err411); -} -errors++; -} -} -if(data229.text !== undefined){ -let data230 = data229.text; -if((data230 !== null) && (typeof data230 !== "string")){ -const err412 = {instancePath:instancePath+"/inbox/" + i11+"/payload/text",schemaPath:"#/properties/inbox/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err412]; -} -else { -vErrors.push(err412); -} -errors++; -} -} -if(data229.binary !== undefined){ -let data231 = data229.binary; -if((typeof data231 !== "string") && (data231 !== null)){ -const err413 = {instancePath:instancePath+"/inbox/" + i11+"/payload/binary",schemaPath:"#/properties/inbox/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err413]; -} -else { -vErrors.push(err413); -} -errors++; -} -} -if(data229.reference_id !== undefined){ -if(typeof data229.reference_id !== "string"){ -const err414 = {instancePath:instancePath+"/inbox/" + i11+"/payload/reference_id",schemaPath:"#/properties/inbox/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err414]; -} -else { -vErrors.push(err414); -} -errors++; -} -} -if(data229.digest !== undefined){ -if(typeof data229.digest !== "string"){ -const err415 = {instancePath:instancePath+"/inbox/" + i11+"/payload/digest",schemaPath:"#/properties/inbox/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err415]; -} -else { -vErrors.push(err415); -} -errors++; -} -} -if(data229.size !== undefined){ -let data234 = data229.size; -if(typeof data234 === "string"){ -if(!pattern0.test(data234)){ -const err416 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err416]; -} -else { -vErrors.push(err416); -} -errors++; -} -if(!(formats0.validate(data234))){ -const err417 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err417]; -} -else { -vErrors.push(err417); -} -errors++; -} -} -else { -const err418 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err418]; -} -else { -vErrors.push(err418); -} -errors++; -} -} -if(data229.media_type !== undefined){ -if(typeof data229.media_type !== "string"){ -const err419 = {instancePath:instancePath+"/inbox/" + i11+"/payload/media_type",schemaPath:"#/properties/inbox/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err419]; -} -else { -vErrors.push(err419); -} -errors++; -} -} -if(data229.source !== undefined){ -if(typeof data229.source !== "string"){ -const err420 = {instancePath:instancePath+"/inbox/" + i11+"/payload/source",schemaPath:"#/properties/inbox/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err420]; -} -else { -vErrors.push(err420); -} -errors++; -} -} -} -else { -const err421 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err421]; -} -else { -vErrors.push(err421); -} -errors++; -} -} -} -else { -const err422 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err422]; -} -else { -vErrors.push(err422); -} -errors++; -} -} -} -} -} -else { -const err423 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err423]; -} -else { -vErrors.push(err423); -} -errors++; -} -validate15.errors = vErrors; -return errors === 0; -} - -export const ArchiveParams = validate16; -const schema17 = {"type":"object","properties":{"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ArchiveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ArchiveParams","required":["archived"],"additionalProperties":false}; - -function validate16(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ArchiveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.archived === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "archived")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err2 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate16.errors = vErrors; -return errors === 0; -} - -export const ArchiveResult = validate17; -const schema18 = {"type":"object","properties":{"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ArchiveResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ArchiveResult","required":["archived"],"additionalProperties":false}; - -function validate17(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ArchiveResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.archived === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "archived")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err2 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate17.errors = vErrors; -return errors === 0; -} - -export const BoundedTranscriptPage = validate18; -const schema19 = {"type":"object","properties":{"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"through_seq":{"type":"integer"},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":false},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false}},"required":["invocation_id","name","status"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":false},"role":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"seq":{"type":"integer"},"message":{"type":["null","object"],"properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":false},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false}},"required":["invocation_id","name","status"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":false},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":false},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":false}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":false},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["seq"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/BoundedTranscriptPage","$schema":"http://json-schema.org/draft-07/schema#","title":"BoundedTranscriptPage","required":["history_revision","through_seq","next_seq","has_more","messages"],"additionalProperties":false}; - -function validate18(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BoundedTranscriptPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.history_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.through_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.next_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.messages === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "history_revision") || (key0 === "through_seq")) || (key0 === "next_seq")) || (key0 === "has_more")) || (key0 === "messages"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.history_revision !== undefined){ -let data0 = data.history_revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err6 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err7 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.through_seq !== undefined){ -let data1 = data.through_seq; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err9 = {instancePath:instancePath+"/through_seq",schemaPath:"#/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.next_seq !== undefined){ -let data2 = data.next_seq; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err10 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err11 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.messages !== undefined){ -let data4 = data.messages; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err12 = {instancePath:instancePath+"/messages",schemaPath:"#/properties/messages/type",keyword:"type",params:{type: schema19.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -let data5 = data4[i0]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.seq === undefined){ -const err13 = {instancePath:instancePath+"/messages/" + i0,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key1 in data5){ -if(!(((((((key1 === "presentation") || (key1 === "role")) || (key1 === "authored")) || (key1 === "sent_at")) || (key1 === "seq")) || (key1 === "message")) || (key1 === "body"))){ -const err14 = {instancePath:instancePath+"/messages/" + i0,schemaPath:"#/properties/messages/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data5.presentation !== undefined){ -let data6 = data5.presentation; -if((data6 !== null) && (!(data6 && typeof data6 == "object" && !Array.isArray(data6)))){ -const err15 = {instancePath:instancePath+"/messages/" + i0+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.version === undefined){ -const err16 = {instancePath:instancePath+"/messages/" + i0+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -for(const key2 in data6){ -if(!(((((key2 === "design_context") || (key2 === "version")) || (key2 === "turn_id")) || (key2 === "parts")) || (key2 === "omitted"))){ -const err17 = {instancePath:instancePath+"/messages/" + i0+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data6.design_context !== undefined){ -let data7 = data6.design_context; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err18 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.context_attachment_id === undefined){ -const err19 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.elements === undefined){ -const err20 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data7.element_count === undefined){ -const err21 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data7.context_part_index === undefined){ -const err22 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -for(const key3 in data7){ -if(!((((((((key3 === "context_attachment_id") || (key3 === "screenshot_attachment_id")) || (key3 === "elements")) || (key3 === "element_count")) || (key3 === "page_url")) || (key3 === "page_title")) || (key3 === "context_part_index")) || (key3 === "screenshot_part_index"))){ -const err23 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data7.context_attachment_id !== undefined){ -if(typeof data7.context_attachment_id !== "string"){ -const err24 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.screenshot_attachment_id !== undefined){ -if(typeof data7.screenshot_attachment_id !== "string"){ -const err25 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.elements !== undefined){ -let data10 = data7.elements; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err26 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -let data11 = data10[i1]; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.label === undefined){ -const err27 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -for(const key4 in data11){ -if(!((key4 === "label") || (key4 === "selector"))){ -const err28 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data11.label !== undefined){ -if(typeof data11.label !== "string"){ -const err29 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1+"/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data11.selector !== undefined){ -if(typeof data11.selector !== "string"){ -const err30 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1+"/selector",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -else { -const err31 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -} -if(data7.element_count !== undefined){ -let data14 = data7.element_count; -if(!((typeof data14 == "number") && (!(data14 % 1) && !isNaN(data14)))){ -const err32 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data7.page_url !== undefined){ -if(typeof data7.page_url !== "string"){ -const err33 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data7.page_title !== undefined){ -if(typeof data7.page_title !== "string"){ -const err34 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data7.context_part_index !== undefined){ -let data17 = data7.context_part_index; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err35 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data7.screenshot_part_index !== undefined){ -let data18 = data7.screenshot_part_index; -if((data18 !== null) && (!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18))))){ -const err36 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -} -if(data6.version !== undefined){ -let data19 = data6.version; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err37 = {instancePath:instancePath+"/messages/" + i0+"/presentation/version",schemaPath:"#/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data6.turn_id !== undefined){ -if(typeof data6.turn_id !== "string"){ -const err38 = {instancePath:instancePath+"/messages/" + i0+"/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data6.parts !== undefined){ -let data21 = data6.parts; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err39 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(Array.isArray(data21)){ -const len2 = data21.length; -for(let i2=0; i2<len2; i2++){ -let data22 = data21[i2]; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.id === undefined){ -const err40 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data22.kind === undefined){ -const err41 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -for(const key5 in data22){ -if(!(func2.call(schema19.properties.messages.items.properties.presentation.properties.parts.items.properties, key5))){ -const err42 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data22.id !== undefined){ -if(typeof data22.id !== "string"){ -const err43 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data22.kind !== undefined){ -if(typeof data22.kind !== "string"){ -const err44 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/kind",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data22.start !== undefined){ -let data25 = data22.start; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err45 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/start",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data22.end !== undefined){ -let data26 = data22.end; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err46 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/end",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data22.text !== undefined){ -if(typeof data22.text !== "string"){ -const err47 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/text",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data22.tool_name !== undefined){ -if(typeof data22.tool_name !== "string"){ -const err48 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/tool_name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data22.status !== undefined){ -if(typeof data22.status !== "string"){ -const err49 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data22.call_id !== undefined){ -if(typeof data22.call_id !== "string"){ -const err50 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/call_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data22.hosts !== undefined){ -let data31 = data22.hosts; -if((data31 !== null) && (!(Array.isArray(data31)))){ -const err51 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(Array.isArray(data31)){ -const len3 = data31.length; -for(let i3=0; i3<len3; i3++){ -let data32 = data31[i3]; -if(data32 && typeof data32 == "object" && !Array.isArray(data32)){ -if(data32.invocation_id === undefined){ -const err52 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data32.name === undefined){ -const err53 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data32.status === undefined){ -const err54 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -for(const key6 in data32){ -if(!(((((((key6 === "invocation_id") || (key6 === "name")) || (key6 === "summary")) || (key6 === "status")) || (key6 === "duration")) || (key6 === "error")) || (key6 === "display"))){ -const err55 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data32.invocation_id !== undefined){ -if(typeof data32.invocation_id !== "string"){ -const err56 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/invocation_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data32.name !== undefined){ -if(typeof data32.name !== "string"){ -const err57 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data32.summary !== undefined){ -if(typeof data32.summary !== "string"){ -const err58 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/summary",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data32.status !== undefined){ -if(typeof data32.status !== "string"){ -const err59 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data32.duration !== undefined){ -if(typeof data32.duration !== "string"){ -const err60 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/duration",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data32.error !== undefined){ -if(typeof data32.error !== "string"){ -const err61 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/error",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data32.display !== undefined){ -let data39 = data32.display; -if((data39 !== null) && (!(data39 && typeof data39 == "object" && !Array.isArray(data39)))){ -const err62 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data39 && typeof data39 == "object" && !Array.isArray(data39)){ -for(const key7 in data39){ -if(!(((((key7 === "target") || (key7 === "command")) || (key7 === "query")) || (key7 === "child_id")) || (key7 === "label"))){ -const err63 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data39.target !== undefined){ -if(typeof data39.target !== "string"){ -const err64 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/target",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data39.command !== undefined){ -if(typeof data39.command !== "string"){ -const err65 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/command",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data39.query !== undefined){ -if(typeof data39.query !== "string"){ -const err66 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/query",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data39.child_id !== undefined){ -if(typeof data39.child_id !== "string"){ -const err67 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/child_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data39.label !== undefined){ -if(typeof data39.label !== "string"){ -const err68 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -} -else { -const err69 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -} -if(data22.omitted !== undefined){ -let data45 = data22.omitted; -if(!((typeof data45 == "number") && (!(data45 % 1) && !isNaN(data45)))){ -const err70 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -} -else { -const err71 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -} -} -if(data6.omitted !== undefined){ -let data46 = data6.omitted; -if(!((typeof data46 == "number") && (!(data46 % 1) && !isNaN(data46)))){ -const err72 = {instancePath:instancePath+"/messages/" + i0+"/presentation/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -} -if(data5.role !== undefined){ -if(typeof data5.role !== "string"){ -const err73 = {instancePath:instancePath+"/messages/" + i0+"/role",schemaPath:"#/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data5.authored !== undefined){ -if(typeof data5.authored !== "boolean"){ -const err74 = {instancePath:instancePath+"/messages/" + i0+"/authored",schemaPath:"#/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data5.sent_at !== undefined){ -let data49 = data5.sent_at; -if((data49 !== null) && (typeof data49 !== "string")){ -const err75 = {instancePath:instancePath+"/messages/" + i0+"/sent_at",schemaPath:"#/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data5.seq !== undefined){ -let data50 = data5.seq; -if(!((typeof data50 == "number") && (!(data50 % 1) && !isNaN(data50)))){ -const err76 = {instancePath:instancePath+"/messages/" + i0+"/seq",schemaPath:"#/properties/messages/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data5.message !== undefined){ -let data51 = data5.message; -if((data51 !== null) && (!(data51 && typeof data51 == "object" && !Array.isArray(data51)))){ -const err77 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.role === undefined){ -const err78 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data51.content === undefined){ -const err79 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -for(const key8 in data51){ -if(!(func2.call(schema19.properties.messages.items.properties.message.properties, key8))){ -const err80 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data51.presentation !== undefined){ -let data52 = data51.presentation; -if((data52 !== null) && (!(data52 && typeof data52 == "object" && !Array.isArray(data52)))){ -const err81 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data52 && typeof data52 == "object" && !Array.isArray(data52)){ -if(data52.version === undefined){ -const err82 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -for(const key9 in data52){ -if(!(((((key9 === "design_context") || (key9 === "version")) || (key9 === "turn_id")) || (key9 === "parts")) || (key9 === "omitted"))){ -const err83 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data52.design_context !== undefined){ -let data53 = data52.design_context; -if((data53 !== null) && (!(data53 && typeof data53 == "object" && !Array.isArray(data53)))){ -const err84 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data53 && typeof data53 == "object" && !Array.isArray(data53)){ -if(data53.context_attachment_id === undefined){ -const err85 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data53.elements === undefined){ -const err86 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data53.element_count === undefined){ -const err87 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(data53.context_part_index === undefined){ -const err88 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -for(const key10 in data53){ -if(!((((((((key10 === "context_attachment_id") || (key10 === "screenshot_attachment_id")) || (key10 === "elements")) || (key10 === "element_count")) || (key10 === "page_url")) || (key10 === "page_title")) || (key10 === "context_part_index")) || (key10 === "screenshot_part_index"))){ -const err89 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data53.context_attachment_id !== undefined){ -if(typeof data53.context_attachment_id !== "string"){ -const err90 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data53.screenshot_attachment_id !== undefined){ -if(typeof data53.screenshot_attachment_id !== "string"){ -const err91 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data53.elements !== undefined){ -let data56 = data53.elements; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err92 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -if(Array.isArray(data56)){ -const len4 = data56.length; -for(let i4=0; i4<len4; i4++){ -let data57 = data56[i4]; -if(data57 && typeof data57 == "object" && !Array.isArray(data57)){ -if(data57.label === undefined){ -const err93 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -for(const key11 in data57){ -if(!((key11 === "label") || (key11 === "selector"))){ -const err94 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data57.label !== undefined){ -if(typeof data57.label !== "string"){ -const err95 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4+"/label",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data57.selector !== undefined){ -if(typeof data57.selector !== "string"){ -const err96 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4+"/selector",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -} -else { -const err97 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -} -if(data53.element_count !== undefined){ -let data60 = data53.element_count; -if(!((typeof data60 == "number") && (!(data60 % 1) && !isNaN(data60)))){ -const err98 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data53.page_url !== undefined){ -if(typeof data53.page_url !== "string"){ -const err99 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data53.page_title !== undefined){ -if(typeof data53.page_title !== "string"){ -const err100 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data53.context_part_index !== undefined){ -let data63 = data53.context_part_index; -if(!((typeof data63 == "number") && (!(data63 % 1) && !isNaN(data63)))){ -const err101 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data53.screenshot_part_index !== undefined){ -let data64 = data53.screenshot_part_index; -if((data64 !== null) && (!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64))))){ -const err102 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -} -} -if(data52.version !== undefined){ -let data65 = data52.version; -if(!((typeof data65 == "number") && (!(data65 % 1) && !isNaN(data65)))){ -const err103 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/version",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data52.turn_id !== undefined){ -if(typeof data52.turn_id !== "string"){ -const err104 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data52.parts !== undefined){ -let data67 = data52.parts; -if((data67 !== null) && (!(Array.isArray(data67)))){ -const err105 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(Array.isArray(data67)){ -const len5 = data67.length; -for(let i5=0; i5<len5; i5++){ -let data68 = data67[i5]; -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -if(data68.id === undefined){ -const err106 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(data68.kind === undefined){ -const err107 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -for(const key12 in data68){ -if(!(func2.call(schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties, key12))){ -const err108 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data68.id !== undefined){ -if(typeof data68.id !== "string"){ -const err109 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data68.kind !== undefined){ -if(typeof data68.kind !== "string"){ -const err110 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/kind",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data68.start !== undefined){ -let data71 = data68.start; -if(!((typeof data71 == "number") && (!(data71 % 1) && !isNaN(data71)))){ -const err111 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/start",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data68.end !== undefined){ -let data72 = data68.end; -if(!((typeof data72 == "number") && (!(data72 % 1) && !isNaN(data72)))){ -const err112 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/end",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data68.text !== undefined){ -if(typeof data68.text !== "string"){ -const err113 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/text",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data68.tool_name !== undefined){ -if(typeof data68.tool_name !== "string"){ -const err114 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/tool_name",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data68.status !== undefined){ -if(typeof data68.status !== "string"){ -const err115 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/status",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data68.call_id !== undefined){ -if(typeof data68.call_id !== "string"){ -const err116 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/call_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data68.hosts !== undefined){ -let data77 = data68.hosts; -if((data77 !== null) && (!(Array.isArray(data77)))){ -const err117 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(Array.isArray(data77)){ -const len6 = data77.length; -for(let i6=0; i6<len6; i6++){ -let data78 = data77[i6]; -if(data78 && typeof data78 == "object" && !Array.isArray(data78)){ -if(data78.invocation_id === undefined){ -const err118 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data78.name === undefined){ -const err119 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data78.status === undefined){ -const err120 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -for(const key13 in data78){ -if(!(((((((key13 === "invocation_id") || (key13 === "name")) || (key13 === "summary")) || (key13 === "status")) || (key13 === "duration")) || (key13 === "error")) || (key13 === "display"))){ -const err121 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -if(data78.invocation_id !== undefined){ -if(typeof data78.invocation_id !== "string"){ -const err122 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/invocation_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data78.name !== undefined){ -if(typeof data78.name !== "string"){ -const err123 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/name",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data78.summary !== undefined){ -if(typeof data78.summary !== "string"){ -const err124 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/summary",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data78.status !== undefined){ -if(typeof data78.status !== "string"){ -const err125 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/status",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data78.duration !== undefined){ -if(typeof data78.duration !== "string"){ -const err126 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/duration",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -if(data78.error !== undefined){ -if(typeof data78.error !== "string"){ -const err127 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/error",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data78.display !== undefined){ -let data85 = data78.display; -if((data85 !== null) && (!(data85 && typeof data85 == "object" && !Array.isArray(data85)))){ -const err128 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -if(data85 && typeof data85 == "object" && !Array.isArray(data85)){ -for(const key14 in data85){ -if(!(((((key14 === "target") || (key14 === "command")) || (key14 === "query")) || (key14 === "child_id")) || (key14 === "label"))){ -const err129 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -if(data85.target !== undefined){ -if(typeof data85.target !== "string"){ -const err130 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/target",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -if(data85.command !== undefined){ -if(typeof data85.command !== "string"){ -const err131 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/command",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -if(data85.query !== undefined){ -if(typeof data85.query !== "string"){ -const err132 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/query",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data85.child_id !== undefined){ -if(typeof data85.child_id !== "string"){ -const err133 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/child_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data85.label !== undefined){ -if(typeof data85.label !== "string"){ -const err134 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/label",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -} -} -} -else { -const err135 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -} -} -if(data68.omitted !== undefined){ -let data91 = data68.omitted; -if(!((typeof data91 == "number") && (!(data91 % 1) && !isNaN(data91)))){ -const err136 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/omitted",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -} -else { -const err137 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -} -} -if(data52.omitted !== undefined){ -let data92 = data52.omitted; -if(!((typeof data92 == "number") && (!(data92 % 1) && !isNaN(data92)))){ -const err138 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/omitted",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -if(data51.role !== undefined){ -if(typeof data51.role !== "string"){ -const err139 = {instancePath:instancePath+"/messages/" + i0+"/message/role",schemaPath:"#/properties/messages/items/properties/message/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -if(data51.content !== undefined){ -let data94 = data51.content; -const _errs205 = errors; -let valid29 = false; -const _errs206 = errors; -if(typeof data94 !== "string"){ -const err140 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -var _valid0 = _errs206 === errors; -valid29 = valid29 || _valid0; -if(!valid29){ -const _errs208 = errors; -if(Array.isArray(data94)){ -const len7 = data94.length; -for(let i7=0; i7<len7; i7++){ -let data95 = data94[i7]; -if(data95 && typeof data95 == "object" && !Array.isArray(data95)){ -if(data95.type === undefined){ -const err141 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7,schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -for(const key15 in data95){ -if(!(((((key15 === "type") || (key15 === "text")) || (key15 === "image_url")) || (key15 === "w")) || (key15 === "h"))){ -const err142 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7,schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data95.type !== undefined){ -if(typeof data95.type !== "string"){ -const err143 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/type",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data95.text !== undefined){ -if(typeof data95.text !== "string"){ -const err144 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/text",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -if(data95.image_url !== undefined){ -let data98 = data95.image_url; -if((data98 !== null) && (!(data98 && typeof data98 == "object" && !Array.isArray(data98)))){ -const err145 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -if(data98 && typeof data98 == "object" && !Array.isArray(data98)){ -if(data98.url === undefined){ -const err146 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -for(const key16 in data98){ -if(!(key16 === "url")){ -const err147 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -if(data98.url !== undefined){ -if(typeof data98.url !== "string"){ -const err148 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url/url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -} -} -if(data95.w !== undefined){ -let data100 = data95.w; -if(!((typeof data100 == "number") && (!(data100 % 1) && !isNaN(data100)))){ -const err149 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/w",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -if(data95.h !== undefined){ -let data101 = data95.h; -if(!((typeof data101 == "number") && (!(data101 % 1) && !isNaN(data101)))){ -const err150 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/h",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -} -else { -const err151 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7,schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -} -else { -const err152 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -var _valid0 = _errs208 === errors; -valid29 = valid29 || _valid0; -} -if(!valid29){ -const err153 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -else { -errors = _errs205; -if(vErrors !== null){ -if(_errs205){ -vErrors.length = _errs205; -} -else { -vErrors = null; -} -} -} -} -if(data51.tool_calls !== undefined){ -let data102 = data51.tool_calls; -if((data102 !== null) && (!(Array.isArray(data102)))){ -const err154 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -if(Array.isArray(data102)){ -const len8 = data102.length; -for(let i8=0; i8<len8; i8++){ -let data103 = data102[i8]; -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.id === undefined){ -const err155 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -if(data103.type === undefined){ -const err156 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -if(data103.function === undefined){ -const err157 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -for(const key17 in data103){ -if(!(((((key17 === "id") || (key17 === "type")) || (key17 === "function")) || (key17 === "duration_ms")) || (key17 === "exit_code"))){ -const err158 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key17},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -} -if(data103.id !== undefined){ -if(typeof data103.id !== "string"){ -const err159 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/id",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -} -if(data103.type !== undefined){ -if(typeof data103.type !== "string"){ -const err160 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/type",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data103.function !== undefined){ -let data106 = data103.function; -if(data106 && typeof data106 == "object" && !Array.isArray(data106)){ -if(data106.name === undefined){ -const err161 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -if(data106.arguments === undefined){ -const err162 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -for(const key18 in data106){ -if(!((key18 === "name") || (key18 === "arguments"))){ -const err163 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key18},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -} -if(data106.name !== undefined){ -if(typeof data106.name !== "string"){ -const err164 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function/name",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data106.arguments !== undefined){ -if(typeof data106.arguments !== "string"){ -const err165 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function/arguments",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -} -else { -const err166 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -if(data103.duration_ms !== undefined){ -let data109 = data103.duration_ms; -if(!((typeof data109 == "number") && (!(data109 % 1) && !isNaN(data109)))){ -const err167 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/duration_ms",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -if(data103.exit_code !== undefined){ -let data110 = data103.exit_code; -if(!((typeof data110 == "number") && (!(data110 % 1) && !isNaN(data110)))){ -const err168 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/exit_code",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -} -} -else { -const err169 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -} -} -} -if(data51.tool_call_id !== undefined){ -if(typeof data51.tool_call_id !== "string"){ -const err170 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_call_id",schemaPath:"#/properties/messages/items/properties/message/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -} -if(data51.name !== undefined){ -if(typeof data51.name !== "string"){ -const err171 = {instancePath:instancePath+"/messages/" + i0+"/message/name",schemaPath:"#/properties/messages/items/properties/message/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -} -if(data51.authored !== undefined){ -if(typeof data51.authored !== "boolean"){ -const err172 = {instancePath:instancePath+"/messages/" + i0+"/message/authored",schemaPath:"#/properties/messages/items/properties/message/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -} -if(data51.sent_at !== undefined){ -let data114 = data51.sent_at; -if((data114 !== null) && (typeof data114 !== "string")){ -const err173 = {instancePath:instancePath+"/messages/" + i0+"/message/sent_at",schemaPath:"#/properties/messages/items/properties/message/properties/sent_at/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -if(data51.usage !== undefined){ -let data115 = data51.usage; -if((data115 !== null) && (!(data115 && typeof data115 == "object" && !Array.isArray(data115)))){ -const err174 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -if(data115 && typeof data115 == "object" && !Array.isArray(data115)){ -if(data115.prompt_tokens === undefined){ -const err175 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -if(data115.completion_tokens === undefined){ -const err176 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -for(const key19 in data115){ -if(!((((((key19 === "reported") || (key19 === "cost")) || (key19 === "prompt_tokens")) || (key19 === "completion_tokens")) || (key19 === "prompt_tokens_details")) || (key19 === "completion_tokens_details"))){ -const err177 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key19},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -if(data115.reported !== undefined){ -if(typeof data115.reported !== "boolean"){ -const err178 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/reported",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -if(data115.cost !== undefined){ -let data117 = data115.cost; -if((data117 !== null) && (!(typeof data117 == "number"))){ -const err179 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/cost",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/cost/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -if(data115.prompt_tokens !== undefined){ -let data118 = data115.prompt_tokens; -if(!((typeof data118 == "number") && (!(data118 % 1) && !isNaN(data118)))){ -const err180 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -} -if(data115.completion_tokens !== undefined){ -let data119 = data115.completion_tokens; -if(!((typeof data119 == "number") && (!(data119 % 1) && !isNaN(data119)))){ -const err181 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -} -if(data115.prompt_tokens_details !== undefined){ -let data120 = data115.prompt_tokens_details; -if((data120 !== null) && (!(data120 && typeof data120 == "object" && !Array.isArray(data120)))){ -const err182 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.cached_tokens === undefined){ -const err183 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -for(const key20 in data120){ -if(!(key20 === "cached_tokens")){ -const err184 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key20},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -} -if(data120.cached_tokens !== undefined){ -let data121 = data120.cached_tokens; -if(!((typeof data121 == "number") && (!(data121 % 1) && !isNaN(data121)))){ -const err185 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -} -} -if(data115.completion_tokens_details !== undefined){ -let data122 = data115.completion_tokens_details; -if((data122 !== null) && (!(data122 && typeof data122 == "object" && !Array.isArray(data122)))){ -const err186 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -if(data122 && typeof data122 == "object" && !Array.isArray(data122)){ -if(data122.reasoning_tokens === undefined){ -const err187 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -for(const key21 in data122){ -if(!(key21 === "reasoning_tokens")){ -const err188 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key21},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -} -if(data122.reasoning_tokens !== undefined){ -let data123 = data122.reasoning_tokens; -if(!((typeof data123 == "number") && (!(data123 % 1) && !isNaN(data123)))){ -const err189 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -} -} -} -} -} -if(data51.model !== undefined){ -if(typeof data51.model !== "string"){ -const err190 = {instancePath:instancePath+"/messages/" + i0+"/message/model",schemaPath:"#/properties/messages/items/properties/message/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -} -if(data51.rewound_from !== undefined){ -if(typeof data51.rewound_from !== "string"){ -const err191 = {instancePath:instancePath+"/messages/" + i0+"/message/rewound_from",schemaPath:"#/properties/messages/items/properties/message/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -} -if(data51.call_id !== undefined){ -if(typeof data51.call_id !== "string"){ -const err192 = {instancePath:instancePath+"/messages/" + i0+"/message/call_id",schemaPath:"#/properties/messages/items/properties/message/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -} -} -} -if(data5.body !== undefined){ -let data127 = data5.body; -if((data127 !== null) && (!(data127 && typeof data127 == "object" && !Array.isArray(data127)))){ -const err193 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -if(data127 && typeof data127 == "object" && !Array.isArray(data127)){ -if(data127.reference_id === undefined){ -const err194 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -if(data127.digest === undefined){ -const err195 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(data127.size === undefined){ -const err196 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -if(data127.media_type === undefined){ -const err197 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -if(data127.source === undefined){ -const err198 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -for(const key22 in data127){ -if(!((((((((key22 === "inline") || (key22 === "text")) || (key22 === "binary")) || (key22 === "reference_id")) || (key22 === "digest")) || (key22 === "size")) || (key22 === "media_type")) || (key22 === "source"))){ -const err199 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key22},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -} -if(data127.text !== undefined){ -let data128 = data127.text; -if((data128 !== null) && (typeof data128 !== "string")){ -const err200 = {instancePath:instancePath+"/messages/" + i0+"/body/text",schemaPath:"#/properties/messages/items/properties/body/properties/text/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -} -if(data127.binary !== undefined){ -let data129 = data127.binary; -if((typeof data129 !== "string") && (data129 !== null)){ -const err201 = {instancePath:instancePath+"/messages/" + i0+"/body/binary",schemaPath:"#/properties/messages/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -} -if(data127.reference_id !== undefined){ -if(typeof data127.reference_id !== "string"){ -const err202 = {instancePath:instancePath+"/messages/" + i0+"/body/reference_id",schemaPath:"#/properties/messages/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -} -if(data127.digest !== undefined){ -if(typeof data127.digest !== "string"){ -const err203 = {instancePath:instancePath+"/messages/" + i0+"/body/digest",schemaPath:"#/properties/messages/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -} -if(data127.size !== undefined){ -let data132 = data127.size; -if(typeof data132 === "string"){ -if(!pattern0.test(data132)){ -const err204 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -if(!(formats0.validate(data132))){ -const err205 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -} -else { -const err206 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -} -if(data127.media_type !== undefined){ -if(typeof data127.media_type !== "string"){ -const err207 = {instancePath:instancePath+"/messages/" + i0+"/body/media_type",schemaPath:"#/properties/messages/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -} -if(data127.source !== undefined){ -if(typeof data127.source !== "string"){ -const err208 = {instancePath:instancePath+"/messages/" + i0+"/body/source",schemaPath:"#/properties/messages/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -} -} -} -} -else { -const err209 = {instancePath:instancePath+"/messages/" + i0,schemaPath:"#/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -} -} -} -} -else { -const err210 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -validate18.errors = vErrors; -return errors === 0; -} - -export const BrowserCommand = validate19; -const schema20 = {"type":"object","properties":{"command_id":{"type":"string"},"operation_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"provider_epoch":{"type":"string"},"scope":{"type":"object","properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":false},"expected_document":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/BrowserCommand","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommand","required":["command_id","operation_id","root_id","agent_id","provider_epoch","scope","deadline_millis","kind","arguments"],"additionalProperties":false}; - -function validate19(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommand" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.operation_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.scope === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.kind === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.arguments === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema20.properties, key0))){ -const err9 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err10 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err11 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err12 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err13 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err14 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.scope !== undefined){ -let data5 = data.scope; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.provider_id === undefined){ -const err15 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data5.provider_epoch === undefined){ -const err16 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data5.tab_id === undefined){ -const err17 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data5.tab_generation === undefined){ -const err18 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data5.profile_id === undefined){ -const err19 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data5.rights === undefined){ -const err20 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key1 in data5){ -if(!(func2.call(schema20.properties.scope.properties, key1))){ -const err21 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data5.provider_id !== undefined){ -if(typeof data5.provider_id !== "string"){ -const err22 = {instancePath:instancePath+"/scope/provider_id",schemaPath:"#/properties/scope/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data5.provider_epoch !== undefined){ -if(typeof data5.provider_epoch !== "string"){ -const err23 = {instancePath:instancePath+"/scope/provider_epoch",schemaPath:"#/properties/scope/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data5.tab_id !== undefined){ -if(typeof data5.tab_id !== "string"){ -const err24 = {instancePath:instancePath+"/scope/tab_id",schemaPath:"#/properties/scope/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data5.tab_generation !== undefined){ -if(typeof data5.tab_generation !== "string"){ -const err25 = {instancePath:instancePath+"/scope/tab_generation",schemaPath:"#/properties/scope/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data5.profile_id !== undefined){ -if(typeof data5.profile_id !== "string"){ -const err26 = {instancePath:instancePath+"/scope/profile_id",schemaPath:"#/properties/scope/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data5.attachment_id !== undefined){ -if(typeof data5.attachment_id !== "string"){ -const err27 = {instancePath:instancePath+"/scope/attachment_id",schemaPath:"#/properties/scope/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data5.attachment_generation !== undefined){ -if(typeof data5.attachment_generation !== "string"){ -const err28 = {instancePath:instancePath+"/scope/attachment_generation",schemaPath:"#/properties/scope/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data5.rights !== undefined){ -let data13 = data5.rights; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err29 = {instancePath:instancePath+"/scope/rights",schemaPath:"#/properties/scope/properties/rights/type",keyword:"type",params:{type: schema20.properties.scope.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(Array.isArray(data13)){ -const len0 = data13.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data13[i0] !== "string"){ -const err30 = {instancePath:instancePath+"/scope/rights/" + i0,schemaPath:"#/properties/scope/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -} -if(data5.preview !== undefined){ -let data15 = data5.preview; -if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err31 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/type",keyword:"type",params:{type: schema20.properties.scope.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.host_id === undefined){ -const err32 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data15.host_identity === undefined){ -const err33 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data15.connection_generation === undefined){ -const err34 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data15.environment_id === undefined){ -const err35 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data15.loopback === undefined){ -const err36 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data15.ports === undefined){ -const err37 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -for(const key2 in data15){ -if(!((((((key2 === "host_id") || (key2 === "host_identity")) || (key2 === "connection_generation")) || (key2 === "environment_id")) || (key2 === "loopback")) || (key2 === "ports"))){ -const err38 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data15.host_id !== undefined){ -if(typeof data15.host_id !== "string"){ -const err39 = {instancePath:instancePath+"/scope/preview/host_id",schemaPath:"#/properties/scope/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data15.host_identity !== undefined){ -if(typeof data15.host_identity !== "string"){ -const err40 = {instancePath:instancePath+"/scope/preview/host_identity",schemaPath:"#/properties/scope/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data15.connection_generation !== undefined){ -if(typeof data15.connection_generation !== "string"){ -const err41 = {instancePath:instancePath+"/scope/preview/connection_generation",schemaPath:"#/properties/scope/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data15.environment_id !== undefined){ -if(typeof data15.environment_id !== "string"){ -const err42 = {instancePath:instancePath+"/scope/preview/environment_id",schemaPath:"#/properties/scope/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data15.loopback !== undefined){ -if(typeof data15.loopback !== "string"){ -const err43 = {instancePath:instancePath+"/scope/preview/loopback",schemaPath:"#/properties/scope/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data15.ports !== undefined){ -let data21 = data15.ports; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err44 = {instancePath:instancePath+"/scope/preview/ports",schemaPath:"#/properties/scope/properties/preview/properties/ports/type",keyword:"type",params:{type: schema20.properties.scope.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(Array.isArray(data21)){ -const len1 = data21.length; -for(let i1=0; i1<len1; i1++){ -let data22 = data21[i1]; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err45 = {instancePath:instancePath+"/scope/preview/ports/" + i1,schemaPath:"#/properties/scope/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -} -} -} -} -else { -const err46 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data.expected_document !== undefined){ -if(typeof data.expected_document !== "string"){ -const err47 = {instancePath:instancePath+"/expected_document",schemaPath:"#/properties/expected_document/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data24 = data.deadline_millis; -if(typeof data24 === "string"){ -if(!pattern0.test(data24)){ -const err48 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(!(formats0.validate(data24))){ -const err49 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -else { -const err50 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err51 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -else { -const err52 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -validate19.errors = vErrors; -return errors === 0; -} - -export const BrowserCommandCancel = validate20; -const schema21 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"attachment_generation":{"type":"string"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserCommandCancel","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommandCancel","required":["command_id","root_id","provider_epoch","attachment_generation","reason"],"additionalProperties":false}; - -function validate20(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommandCancel" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.reason === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "command_id") || (key0 === "root_id")) || (key0 === "provider_epoch")) || (key0 === "attachment_generation")) || (key0 === "reason"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err6 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err8 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err9 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err10 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate20.errors = vErrors; -return errors === 0; -} - -export const BrowserCommandResultParams = validate21; -const schema22 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"attachment_generation":{"type":"string"},"document_revision":{"type":"string"},"result":true,"error":{"type":["null","object"],"properties":{"kind":{"type":"string"},"message":{"type":"string"}},"required":["kind","message"],"additionalProperties":false},"screenshot":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/BrowserCommandResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommandResultParams","required":["command_id","root_id","provider_epoch","attachment_generation","document_revision"],"additionalProperties":false}; - -function validate21(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommandResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.document_revision === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!((((((((key0 === "command_id") || (key0 === "root_id")) || (key0 === "provider_epoch")) || (key0 === "attachment_generation")) || (key0 === "document_revision")) || (key0 === "result")) || (key0 === "error")) || (key0 === "screenshot"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err6 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err8 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err9 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.document_revision !== undefined){ -if(typeof data.document_revision !== "string"){ -const err10 = {instancePath:instancePath+"/document_revision",schemaPath:"#/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.error !== undefined){ -let data5 = data.error; -if((data5 !== null) && (!(data5 && typeof data5 == "object" && !Array.isArray(data5)))){ -const err11 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema22.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.kind === undefined){ -const err12 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data5.message === undefined){ -const err13 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key1 in data5){ -if(!((key1 === "kind") || (key1 === "message"))){ -const err14 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data5.kind !== undefined){ -if(typeof data5.kind !== "string"){ -const err15 = {instancePath:instancePath+"/error/kind",schemaPath:"#/properties/error/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data5.message !== undefined){ -if(typeof data5.message !== "string"){ -const err16 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -if(data.screenshot !== undefined){ -let data8 = data.screenshot; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err17 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/type",keyword:"type",params:{type: schema22.properties.screenshot.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.reference_id === undefined){ -const err18 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data8.digest === undefined){ -const err19 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data8.size === undefined){ -const err20 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key2 in data8){ -if(!(((((key2 === "reference_id") || (key2 === "digest")) || (key2 === "size")) || (key2 === "media_type")) || (key2 === "source"))){ -const err21 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data8.reference_id !== undefined){ -if(typeof data8.reference_id !== "string"){ -const err22 = {instancePath:instancePath+"/screenshot/reference_id",schemaPath:"#/properties/screenshot/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data8.digest !== undefined){ -if(typeof data8.digest !== "string"){ -const err23 = {instancePath:instancePath+"/screenshot/digest",schemaPath:"#/properties/screenshot/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data8.size !== undefined){ -let data11 = data8.size; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err24 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err25 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data8.media_type !== undefined){ -if(typeof data8.media_type !== "string"){ -const err27 = {instancePath:instancePath+"/screenshot/media_type",schemaPath:"#/properties/screenshot/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data8.source !== undefined){ -if(typeof data8.source !== "string"){ -const err28 = {instancePath:instancePath+"/screenshot/source",schemaPath:"#/properties/screenshot/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -} -else { -const err29 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -validate21.errors = vErrors; -return errors === 0; -} - -export const BrowserDriverParams = validate22; -const schema23 = {"type":"object","properties":{"driver":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserDriverParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserDriverParams","required":["driver"],"additionalProperties":false}; - -function validate22(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserDriverParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.driver === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "driver"},message:"must have required property '"+"driver"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "driver")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.driver !== undefined){ -if(typeof data.driver !== "string"){ -const err2 = {instancePath:instancePath+"/driver",schemaPath:"#/properties/driver/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate22.errors = vErrors; -return errors === 0; -} - -export const BrowserInventoryRequest = validate23; -const schema24 = {"type":"object","properties":{"request_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"}},"required":["tab_id","tab_generation"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/BrowserInventoryRequest","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserInventoryRequest","required":["request_id","root_id","agent_id","provider_id","provider_epoch","tabs"],"additionalProperties":false}; - -function validate23(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserInventoryRequest" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.request_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "request_id"},message:"must have required property '"+"request_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.agent_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.provider_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.tabs === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tabs"},message:"must have required property '"+"tabs"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "request_id") || (key0 === "root_id")) || (key0 === "agent_id")) || (key0 === "provider_id")) || (key0 === "provider_epoch")) || (key0 === "tabs"))){ -const err6 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.request_id !== undefined){ -if(typeof data.request_id !== "string"){ -const err7 = {instancePath:instancePath+"/request_id",schemaPath:"#/properties/request_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err8 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err9 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err10 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err11 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.tabs !== undefined){ -let data5 = data.tabs; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err12 = {instancePath:instancePath+"/tabs",schemaPath:"#/properties/tabs/type",keyword:"type",params:{type: schema24.properties.tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -let data6 = data5[i0]; -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.tab_id === undefined){ -const err13 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data6.tab_generation === undefined){ -const err14 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -for(const key1 in data6){ -if(!((key1 === "tab_id") || (key1 === "tab_generation"))){ -const err15 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data6.tab_id !== undefined){ -if(typeof data6.tab_id !== "string"){ -const err16 = {instancePath:instancePath+"/tabs/" + i0+"/tab_id",schemaPath:"#/properties/tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data6.tab_generation !== undefined){ -if(typeof data6.tab_generation !== "string"){ -const err17 = {instancePath:instancePath+"/tabs/" + i0+"/tab_generation",schemaPath:"#/properties/tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -} -else { -const err19 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -validate23.errors = vErrors; -return errors === 0; -} - -export const BrowserInventoryResultParams = validate24; -const schema25 = {"type":"object","properties":{"request_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"document_revision":{"type":"string"},"url":{"type":"string"},"title":{"type":"string"},"state":{"type":"string"},"requestable":{"type":"boolean"},"attachment_id":{"type":"string"}},"required":["tab_id","tab_generation","document_revision","url","title","state","requestable"],"additionalProperties":false}},"error":{"type":["null","object"],"properties":{"kind":{"type":"string"},"message":{"type":"string"}},"required":["kind","message"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/BrowserInventoryResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserInventoryResultParams","required":["request_id","root_id","provider_epoch","tabs"],"additionalProperties":false}; - -function validate24(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserInventoryResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.request_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "request_id"},message:"must have required property '"+"request_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.tabs === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tabs"},message:"must have required property '"+"tabs"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "request_id") || (key0 === "root_id")) || (key0 === "provider_epoch")) || (key0 === "tabs")) || (key0 === "error"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.request_id !== undefined){ -if(typeof data.request_id !== "string"){ -const err5 = {instancePath:instancePath+"/request_id",schemaPath:"#/properties/request_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err7 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.tabs !== undefined){ -let data3 = data.tabs; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/tabs",schemaPath:"#/properties/tabs/type",keyword:"type",params:{type: schema25.properties.tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.tab_id === undefined){ -const err9 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.tab_generation === undefined){ -const err10 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.document_revision === undefined){ -const err11 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data4.url === undefined){ -const err12 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data4.title === undefined){ -const err13 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data4.state === undefined){ -const err14 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data4.requestable === undefined){ -const err15 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "requestable"},message:"must have required property '"+"requestable"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -for(const key1 in data4){ -if(!((((((((key1 === "tab_id") || (key1 === "tab_generation")) || (key1 === "document_revision")) || (key1 === "url")) || (key1 === "title")) || (key1 === "state")) || (key1 === "requestable")) || (key1 === "attachment_id"))){ -const err16 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data4.tab_id !== undefined){ -if(typeof data4.tab_id !== "string"){ -const err17 = {instancePath:instancePath+"/tabs/" + i0+"/tab_id",schemaPath:"#/properties/tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data4.tab_generation !== undefined){ -if(typeof data4.tab_generation !== "string"){ -const err18 = {instancePath:instancePath+"/tabs/" + i0+"/tab_generation",schemaPath:"#/properties/tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data4.document_revision !== undefined){ -if(typeof data4.document_revision !== "string"){ -const err19 = {instancePath:instancePath+"/tabs/" + i0+"/document_revision",schemaPath:"#/properties/tabs/items/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data4.url !== undefined){ -if(typeof data4.url !== "string"){ -const err20 = {instancePath:instancePath+"/tabs/" + i0+"/url",schemaPath:"#/properties/tabs/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data4.title !== undefined){ -if(typeof data4.title !== "string"){ -const err21 = {instancePath:instancePath+"/tabs/" + i0+"/title",schemaPath:"#/properties/tabs/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data4.state !== undefined){ -if(typeof data4.state !== "string"){ -const err22 = {instancePath:instancePath+"/tabs/" + i0+"/state",schemaPath:"#/properties/tabs/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data4.requestable !== undefined){ -if(typeof data4.requestable !== "boolean"){ -const err23 = {instancePath:instancePath+"/tabs/" + i0+"/requestable",schemaPath:"#/properties/tabs/items/properties/requestable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data4.attachment_id !== undefined){ -if(typeof data4.attachment_id !== "string"){ -const err24 = {instancePath:instancePath+"/tabs/" + i0+"/attachment_id",schemaPath:"#/properties/tabs/items/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data.error !== undefined){ -let data13 = data.error; -if((data13 !== null) && (!(data13 && typeof data13 == "object" && !Array.isArray(data13)))){ -const err26 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema25.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.kind === undefined){ -const err27 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data13.message === undefined){ -const err28 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -for(const key2 in data13){ -if(!((key2 === "kind") || (key2 === "message"))){ -const err29 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data13.kind !== undefined){ -if(typeof data13.kind !== "string"){ -const err30 = {instancePath:instancePath+"/error/kind",schemaPath:"#/properties/error/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data13.message !== undefined){ -if(typeof data13.message !== "string"){ -const err31 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -} -} -else { -const err32 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -validate24.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderBindParams = validate25; -const schema26 = {"type":"object","properties":{"availability":{"type":"boolean"},"root_id":{"type":"string"},"version":{"type":"integer"},"desktop_id":{"type":"string"},"window_id":{"type":"string"},"offer_revision":{"type":"string"},"create_profile_id":{"type":"string"},"expected_provider_epoch":{"type":"string"},"offered_tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"document_revision":{"type":"string"},"url":{"type":"string"},"title":{"type":"string"},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["tab_id","tab_generation","profile_id"],"additionalProperties":false}},"offered_preview_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/BrowserProviderBindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderBindParams","required":["root_id","version","desktop_id","window_id","offer_revision","create_profile_id","offered_tabs","offered_preview_hosts"],"additionalProperties":false}; - -function validate25(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderBindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.version === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.desktop_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "desktop_id"},message:"must have required property '"+"desktop_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.window_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "window_id"},message:"must have required property '"+"window_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.offer_revision === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offer_revision"},message:"must have required property '"+"offer_revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.create_profile_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "create_profile_id"},message:"must have required property '"+"create_profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.offered_tabs === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered_tabs"},message:"must have required property '"+"offered_tabs"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.offered_preview_hosts === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered_preview_hosts"},message:"must have required property '"+"offered_preview_hosts"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema26.properties, key0))){ -const err8 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.availability !== undefined){ -if(typeof data.availability !== "boolean"){ -const err9 = {instancePath:instancePath+"/availability",schemaPath:"#/properties/availability/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err10 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.version !== undefined){ -let data2 = data.version; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err11 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.desktop_id !== undefined){ -if(typeof data.desktop_id !== "string"){ -const err12 = {instancePath:instancePath+"/desktop_id",schemaPath:"#/properties/desktop_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.window_id !== undefined){ -if(typeof data.window_id !== "string"){ -const err13 = {instancePath:instancePath+"/window_id",schemaPath:"#/properties/window_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.offer_revision !== undefined){ -if(typeof data.offer_revision !== "string"){ -const err14 = {instancePath:instancePath+"/offer_revision",schemaPath:"#/properties/offer_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.create_profile_id !== undefined){ -if(typeof data.create_profile_id !== "string"){ -const err15 = {instancePath:instancePath+"/create_profile_id",schemaPath:"#/properties/create_profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.expected_provider_epoch !== undefined){ -if(typeof data.expected_provider_epoch !== "string"){ -const err16 = {instancePath:instancePath+"/expected_provider_epoch",schemaPath:"#/properties/expected_provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.offered_tabs !== undefined){ -let data8 = data.offered_tabs; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err17 = {instancePath:instancePath+"/offered_tabs",schemaPath:"#/properties/offered_tabs/type",keyword:"type",params:{type: schema26.properties.offered_tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(Array.isArray(data8)){ -const len0 = data8.length; -for(let i0=0; i0<len0; i0++){ -let data9 = data8[i0]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.tab_id === undefined){ -const err18 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data9.tab_generation === undefined){ -const err19 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data9.profile_id === undefined){ -const err20 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key1 in data9){ -if(!(((((((key1 === "tab_id") || (key1 === "tab_generation")) || (key1 === "profile_id")) || (key1 === "document_revision")) || (key1 === "url")) || (key1 === "title")) || (key1 === "preview"))){ -const err21 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data9.tab_id !== undefined){ -if(typeof data9.tab_id !== "string"){ -const err22 = {instancePath:instancePath+"/offered_tabs/" + i0+"/tab_id",schemaPath:"#/properties/offered_tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data9.tab_generation !== undefined){ -if(typeof data9.tab_generation !== "string"){ -const err23 = {instancePath:instancePath+"/offered_tabs/" + i0+"/tab_generation",schemaPath:"#/properties/offered_tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data9.profile_id !== undefined){ -if(typeof data9.profile_id !== "string"){ -const err24 = {instancePath:instancePath+"/offered_tabs/" + i0+"/profile_id",schemaPath:"#/properties/offered_tabs/items/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data9.document_revision !== undefined){ -if(typeof data9.document_revision !== "string"){ -const err25 = {instancePath:instancePath+"/offered_tabs/" + i0+"/document_revision",schemaPath:"#/properties/offered_tabs/items/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data9.url !== undefined){ -if(typeof data9.url !== "string"){ -const err26 = {instancePath:instancePath+"/offered_tabs/" + i0+"/url",schemaPath:"#/properties/offered_tabs/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data9.title !== undefined){ -if(typeof data9.title !== "string"){ -const err27 = {instancePath:instancePath+"/offered_tabs/" + i0+"/title",schemaPath:"#/properties/offered_tabs/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data9.preview !== undefined){ -let data16 = data9.preview; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err28 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/type",keyword:"type",params:{type: schema26.properties.offered_tabs.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.host_id === undefined){ -const err29 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data16.host_identity === undefined){ -const err30 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data16.connection_generation === undefined){ -const err31 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data16.environment_id === undefined){ -const err32 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data16.loopback === undefined){ -const err33 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data16.ports === undefined){ -const err34 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -for(const key2 in data16){ -if(!((((((key2 === "host_id") || (key2 === "host_identity")) || (key2 === "connection_generation")) || (key2 === "environment_id")) || (key2 === "loopback")) || (key2 === "ports"))){ -const err35 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data16.host_id !== undefined){ -if(typeof data16.host_id !== "string"){ -const err36 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/host_id",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data16.host_identity !== undefined){ -if(typeof data16.host_identity !== "string"){ -const err37 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/host_identity",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data16.connection_generation !== undefined){ -if(typeof data16.connection_generation !== "string"){ -const err38 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/connection_generation",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data16.environment_id !== undefined){ -if(typeof data16.environment_id !== "string"){ -const err39 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/environment_id",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data16.loopback !== undefined){ -if(typeof data16.loopback !== "string"){ -const err40 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/loopback",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data16.ports !== undefined){ -let data22 = data16.ports; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err41 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/ports",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/ports/type",keyword:"type",params:{type: schema26.properties.offered_tabs.items.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(Array.isArray(data22)){ -const len1 = data22.length; -for(let i1=0; i1<len1; i1++){ -let data23 = data22[i1]; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err42 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/ports/" + i1,schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -} -} -} -} -else { -const err43 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -} -if(data.offered_preview_hosts !== undefined){ -let data24 = data.offered_preview_hosts; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err44 = {instancePath:instancePath+"/offered_preview_hosts",schemaPath:"#/properties/offered_preview_hosts/type",keyword:"type",params:{type: schema26.properties.offered_preview_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(Array.isArray(data24)){ -const len2 = data24.length; -for(let i2=0; i2<len2; i2++){ -let data25 = data24[i2]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.host_id === undefined){ -const err45 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data25.host_identity === undefined){ -const err46 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data25.connection_generation === undefined){ -const err47 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data25.environment_id === undefined){ -const err48 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data25.loopback === undefined){ -const err49 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data25.ports === undefined){ -const err50 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -for(const key3 in data25){ -if(!((((((key3 === "host_id") || (key3 === "host_identity")) || (key3 === "connection_generation")) || (key3 === "environment_id")) || (key3 === "loopback")) || (key3 === "ports"))){ -const err51 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data25.host_id !== undefined){ -if(typeof data25.host_id !== "string"){ -const err52 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/host_id",schemaPath:"#/properties/offered_preview_hosts/items/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data25.host_identity !== undefined){ -if(typeof data25.host_identity !== "string"){ -const err53 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/host_identity",schemaPath:"#/properties/offered_preview_hosts/items/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data25.connection_generation !== undefined){ -if(typeof data25.connection_generation !== "string"){ -const err54 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/connection_generation",schemaPath:"#/properties/offered_preview_hosts/items/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data25.environment_id !== undefined){ -if(typeof data25.environment_id !== "string"){ -const err55 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/environment_id",schemaPath:"#/properties/offered_preview_hosts/items/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data25.loopback !== undefined){ -if(typeof data25.loopback !== "string"){ -const err56 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/loopback",schemaPath:"#/properties/offered_preview_hosts/items/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data25.ports !== undefined){ -let data31 = data25.ports; -if((data31 !== null) && (!(Array.isArray(data31)))){ -const err57 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/ports",schemaPath:"#/properties/offered_preview_hosts/items/properties/ports/type",keyword:"type",params:{type: schema26.properties.offered_preview_hosts.items.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(Array.isArray(data31)){ -const len3 = data31.length; -for(let i3=0; i3<len3; i3++){ -let data32 = data31[i3]; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err58 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/ports/" + i3,schemaPath:"#/properties/offered_preview_hosts/items/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -} -} -} -else { -const err59 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -} -} -} -else { -const err60 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -validate25.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderBindResult = validate26; -const schema27 = {"type":"object","properties":{"version":{"type":"integer"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderBindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderBindResult","required":["version","provider_id","provider_epoch"],"additionalProperties":false}; - -function validate26(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderBindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.version === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "version") || (key0 === "provider_id")) || (key0 === "provider_epoch"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.version !== undefined){ -let data0 = data.version; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err4 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err5 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err6 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate26.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderEventParams = validate27; -const schema28 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"sequence":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"operation_id":{"type":"string"},"document_revision":{"type":"string"},"kind":{"type":"string"},"method":{"type":"string"},"params":true,"url":{"type":"string"},"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderEventParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderEventParams","required":["root_id","provider_epoch","tab_id","tab_generation","attachment_id","attachment_generation","sequence","document_revision","kind"],"additionalProperties":false}; - -function validate27(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderEventParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.tab_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.tab_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.attachment_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_id"},message:"must have required property '"+"attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.sequence === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "sequence"},message:"must have required property '"+"sequence"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.document_revision === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.kind === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema28.properties, key0))){ -const err9 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err10 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err11 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.tab_id !== undefined){ -if(typeof data.tab_id !== "string"){ -const err12 = {instancePath:instancePath+"/tab_id",schemaPath:"#/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.tab_generation !== undefined){ -if(typeof data.tab_generation !== "string"){ -const err13 = {instancePath:instancePath+"/tab_generation",schemaPath:"#/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.attachment_id !== undefined){ -if(typeof data.attachment_id !== "string"){ -const err14 = {instancePath:instancePath+"/attachment_id",schemaPath:"#/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err15 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.sequence !== undefined){ -let data6 = data.sequence; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err16 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err17 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -else { -const err18 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err19 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.document_revision !== undefined){ -if(typeof data.document_revision !== "string"){ -const err20 = {instancePath:instancePath+"/document_revision",schemaPath:"#/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err21 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.method !== undefined){ -if(typeof data.method !== "string"){ -const err22 = {instancePath:instancePath+"/method",schemaPath:"#/properties/method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.url !== undefined){ -if(typeof data.url !== "string"){ -const err23 = {instancePath:instancePath+"/url",schemaPath:"#/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err24 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -validate27.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderRevoked = validate28; -const schema29 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderRevoked","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderRevoked","required":["root_id","provider_id","provider_epoch","reason"],"additionalProperties":false}; - -function validate28(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderRevoked" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.reason === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "root_id") || (key0 === "provider_id")) || (key0 === "provider_epoch")) || (key0 === "reason"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err6 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err7 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err8 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate28.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderUnbindParams = validate29; -const schema30 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_epoch":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderUnbindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderUnbindParams","required":["root_id","provider_epoch"],"additionalProperties":false}; - -function validate29(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderUnbindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "root_id") || (key0 === "provider_epoch"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err4 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate29.errors = vErrors; -return errors === 0; -} - -export const BrowserStatusResult = validate30; -const schema31 = {"type":"object","properties":{"enabled":{"type":"boolean"},"driver":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserStatusResult","required":["enabled"],"additionalProperties":false}; - -function validate30(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.enabled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "enabled") || (key0 === "driver"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err2 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.driver !== undefined){ -if(typeof data.driver !== "string"){ -const err3 = {instancePath:instancePath+"/driver",schemaPath:"#/properties/driver/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate30.errors = vErrors; -return errors === 0; -} - -export const BudgetCapParams = validate31; -const schema32 = {"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/BudgetCapParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BudgetCapParams","required":["id","kind","limit"],"additionalProperties":false}; - -function validate31(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BudgetCapParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.kind === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "kind")) || (key0 === "limit"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err5 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.limit !== undefined){ -let data2 = data.limit; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err6 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err7 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate31.errors = vErrors; -return errors === 0; -} - -export const BudgetState = validate32; -const schema33 = {"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/BudgetState","$schema":"http://json-schema.org/draft-07/schema#","title":"BudgetState","required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":false}; - -function validate32(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BudgetState" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.kind === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.limit === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.used === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.reserved === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.remaining === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.uncertain === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.incomplete === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "kind") || (key0 === "limit")) || (key0 === "used")) || (key0 === "reserved")) || (key0 === "remaining")) || (key0 === "uncertain")) || (key0 === "incomplete"))){ -const err7 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err8 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.limit !== undefined){ -let data1 = data.limit; -if((typeof data1 !== "string") && (data1 !== null)){ -const err9 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: schema33.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err10 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err11 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -if(data.used !== undefined){ -let data2 = data.used; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err12 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err13 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -else { -const err14 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.reserved !== undefined){ -let data3 = data.reserved; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err15 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err16 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.remaining !== undefined){ -let data4 = data.remaining; -if((typeof data4 !== "string") && (data4 !== null)){ -const err18 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/type",keyword:"type",params:{type: schema33.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err19 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err20 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -if(data.uncertain !== undefined){ -let data5 = data.uncertain; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err21 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err22 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.incomplete !== undefined){ -if(typeof data.incomplete !== "boolean"){ -const err24 = {instancePath:instancePath+"/incomplete",schemaPath:"#/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -validate32.errors = vErrors; -return errors === 0; -} - -export const CancelParams = validate33; -const schema34 = {"type":"object","properties":{"turn_id":{"type":"string"},"target_command_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CancelParams","additionalProperties":false}; - -function validate33(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((key0 === "turn_id") || (key0 === "target_command_id"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err1 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.target_command_id !== undefined){ -if(typeof data.target_command_id !== "string"){ -const err2 = {instancePath:instancePath+"/target_command_id",schemaPath:"#/properties/target_command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate33.errors = vErrors; -return errors === 0; -} - -export const CapabilityRecord = validate34; -const schema35 = {"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":false}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":false},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CapabilityRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"CapabilityRecord","required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":false}; - -function validate34(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CapabilityRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.agent_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.issuer_agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.operations === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.scopes === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.mcp === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.mcp_all === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.generation === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.status === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.expires_at === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.created_at === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.updated_at === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema35.properties, key0))){ -const err13 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err14 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err15 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err16 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.issuer_agent_id !== undefined){ -if(typeof data.issuer_agent_id !== "string"){ -const err17 = {instancePath:instancePath+"/issuer_agent_id",schemaPath:"#/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.operations !== undefined){ -let data4 = data.operations; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err18 = {instancePath:instancePath+"/operations",schemaPath:"#/properties/operations/type",keyword:"type",params:{type: schema35.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err19 = {instancePath:instancePath+"/operations/" + i0,schemaPath:"#/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -} -if(data.scopes !== undefined){ -let data6 = data.scopes; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err20 = {instancePath:instancePath+"/scopes",schemaPath:"#/properties/scopes/type",keyword:"type",params:{type: schema35.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data6[i1] !== "string"){ -const err21 = {instancePath:instancePath+"/scopes/" + i1,schemaPath:"#/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data.file_scope !== undefined){ -if(typeof data.file_scope !== "string"){ -const err22 = {instancePath:instancePath+"/file_scope",schemaPath:"#/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.file_issuer_id !== undefined){ -if(typeof data.file_issuer_id !== "string"){ -const err23 = {instancePath:instancePath+"/file_issuer_id",schemaPath:"#/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.file_issuer_generation !== undefined){ -let data10 = data.file_issuer_generation; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err24 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err25 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data.mcp !== undefined){ -let data11 = data.mcp; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err27 = {instancePath:instancePath+"/mcp",schemaPath:"#/properties/mcp/type",keyword:"type",params:{type: schema35.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -let data12 = data11[i2]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.server === undefined){ -const err28 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data12.tool === undefined){ -const err29 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data12.definition === undefined){ -const err30 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -for(const key1 in data12){ -if(!(((key1 === "server") || (key1 === "tool")) || (key1 === "definition"))){ -const err31 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data12.server !== undefined){ -if(typeof data12.server !== "string"){ -const err32 = {instancePath:instancePath+"/mcp/" + i2+"/server",schemaPath:"#/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data12.tool !== undefined){ -if(typeof data12.tool !== "string"){ -const err33 = {instancePath:instancePath+"/mcp/" + i2+"/tool",schemaPath:"#/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data12.definition !== undefined){ -if(typeof data12.definition !== "string"){ -const err34 = {instancePath:instancePath+"/mcp/" + i2+"/definition",schemaPath:"#/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -else { -const err35 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -} -if(data.mcp_all !== undefined){ -if(typeof data.mcp_all !== "boolean"){ -const err36 = {instancePath:instancePath+"/mcp_all",schemaPath:"#/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data.browser !== undefined){ -let data17 = data.browser; -if((data17 !== null) && (!(data17 && typeof data17 == "object" && !Array.isArray(data17)))){ -const err37 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/type",keyword:"type",params:{type: schema35.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.provider_id === undefined){ -const err38 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data17.provider_epoch === undefined){ -const err39 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data17.tab_id === undefined){ -const err40 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data17.tab_generation === undefined){ -const err41 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data17.profile_id === undefined){ -const err42 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data17.rights === undefined){ -const err43 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -for(const key2 in data17){ -if(!(func2.call(schema35.properties.browser.properties, key2))){ -const err44 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.provider_id !== undefined){ -if(typeof data17.provider_id !== "string"){ -const err45 = {instancePath:instancePath+"/browser/provider_id",schemaPath:"#/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.provider_epoch !== undefined){ -if(typeof data17.provider_epoch !== "string"){ -const err46 = {instancePath:instancePath+"/browser/provider_epoch",schemaPath:"#/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data17.tab_id !== undefined){ -if(typeof data17.tab_id !== "string"){ -const err47 = {instancePath:instancePath+"/browser/tab_id",schemaPath:"#/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data17.tab_generation !== undefined){ -if(typeof data17.tab_generation !== "string"){ -const err48 = {instancePath:instancePath+"/browser/tab_generation",schemaPath:"#/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data17.profile_id !== undefined){ -if(typeof data17.profile_id !== "string"){ -const err49 = {instancePath:instancePath+"/browser/profile_id",schemaPath:"#/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data17.attachment_id !== undefined){ -if(typeof data17.attachment_id !== "string"){ -const err50 = {instancePath:instancePath+"/browser/attachment_id",schemaPath:"#/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data17.attachment_generation !== undefined){ -if(typeof data17.attachment_generation !== "string"){ -const err51 = {instancePath:instancePath+"/browser/attachment_generation",schemaPath:"#/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data17.rights !== undefined){ -let data25 = data17.rights; -if((data25 !== null) && (!(Array.isArray(data25)))){ -const err52 = {instancePath:instancePath+"/browser/rights",schemaPath:"#/properties/browser/properties/rights/type",keyword:"type",params:{type: schema35.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(Array.isArray(data25)){ -const len3 = data25.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data25[i3] !== "string"){ -const err53 = {instancePath:instancePath+"/browser/rights/" + i3,schemaPath:"#/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -} -} -if(data17.preview !== undefined){ -let data27 = data17.preview; -if((data27 !== null) && (!(data27 && typeof data27 == "object" && !Array.isArray(data27)))){ -const err54 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/type",keyword:"type",params:{type: schema35.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data27 && typeof data27 == "object" && !Array.isArray(data27)){ -if(data27.host_id === undefined){ -const err55 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data27.host_identity === undefined){ -const err56 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data27.connection_generation === undefined){ -const err57 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data27.environment_id === undefined){ -const err58 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data27.loopback === undefined){ -const err59 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data27.ports === undefined){ -const err60 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -for(const key3 in data27){ -if(!((((((key3 === "host_id") || (key3 === "host_identity")) || (key3 === "connection_generation")) || (key3 === "environment_id")) || (key3 === "loopback")) || (key3 === "ports"))){ -const err61 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data27.host_id !== undefined){ -if(typeof data27.host_id !== "string"){ -const err62 = {instancePath:instancePath+"/browser/preview/host_id",schemaPath:"#/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data27.host_identity !== undefined){ -if(typeof data27.host_identity !== "string"){ -const err63 = {instancePath:instancePath+"/browser/preview/host_identity",schemaPath:"#/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data27.connection_generation !== undefined){ -if(typeof data27.connection_generation !== "string"){ -const err64 = {instancePath:instancePath+"/browser/preview/connection_generation",schemaPath:"#/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data27.environment_id !== undefined){ -if(typeof data27.environment_id !== "string"){ -const err65 = {instancePath:instancePath+"/browser/preview/environment_id",schemaPath:"#/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data27.loopback !== undefined){ -if(typeof data27.loopback !== "string"){ -const err66 = {instancePath:instancePath+"/browser/preview/loopback",schemaPath:"#/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data27.ports !== undefined){ -let data33 = data27.ports; -if((data33 !== null) && (!(Array.isArray(data33)))){ -const err67 = {instancePath:instancePath+"/browser/preview/ports",schemaPath:"#/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema35.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(Array.isArray(data33)){ -const len4 = data33.length; -for(let i4=0; i4<len4; i4++){ -let data34 = data33[i4]; -if(!((typeof data34 == "number") && (!(data34 % 1) && !isNaN(data34)))){ -const err68 = {instancePath:instancePath+"/browser/preview/ports/" + i4,schemaPath:"#/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -} -} -} -} -if(data.browser_issuer_id !== undefined){ -if(typeof data.browser_issuer_id !== "string"){ -const err69 = {instancePath:instancePath+"/browser_issuer_id",schemaPath:"#/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data.browser_issuer_generation !== undefined){ -let data36 = data.browser_issuer_generation; -if(!((typeof data36 == "number") && (!(data36 % 1) && !isNaN(data36)))){ -const err70 = {instancePath:instancePath+"/browser_issuer_generation",schemaPath:"#/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.browser_delegation_only !== undefined){ -if(typeof data.browser_delegation_only !== "boolean"){ -const err71 = {instancePath:instancePath+"/browser_delegation_only",schemaPath:"#/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.generation !== undefined){ -let data38 = data.generation; -if(typeof data38 === "string"){ -if(!pattern0.test(data38)){ -const err72 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(!(formats0.validate(data38))){ -const err73 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -else { -const err74 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err75 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.expires_at !== undefined){ -if(typeof data.expires_at !== "string"){ -const err76 = {instancePath:instancePath+"/expires_at",schemaPath:"#/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err77 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.updated_at !== undefined){ -if(typeof data.updated_at !== "string"){ -const err78 = {instancePath:instancePath+"/updated_at",schemaPath:"#/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -} -else { -const err79 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -validate34.errors = vErrors; -return errors === 0; -} - -export const CatalogResult = validate35; -const schema36 = {"type":"object","properties":{"themes":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"dark":{"type":"boolean"},"source":{"type":"string"}},"required":["id","name","dark","source"],"additionalProperties":false}},"errors":{"type":["null","array"],"items":{"type":"object","properties":{"file":{"type":"string"},"message":{"type":"string"}},"required":["file","message"],"additionalProperties":false}},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CatalogResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CatalogResult","required":["themes","errors","truncated"],"additionalProperties":false}; - -function validate35(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CatalogResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.themes === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "themes"},message:"must have required property '"+"themes"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.errors === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "errors"},message:"must have required property '"+"errors"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.truncated === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "themes") || (key0 === "errors")) || (key0 === "truncated"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.themes !== undefined){ -let data0 = data.themes; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err4 = {instancePath:instancePath+"/themes",schemaPath:"#/properties/themes/type",keyword:"type",params:{type: schema36.properties.themes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err5 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.name === undefined){ -const err6 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.dark === undefined){ -const err7 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "dark"},message:"must have required property '"+"dark"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.source === undefined){ -const err8 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key1 in data1){ -if(!((((key1 === "id") || (key1 === "name")) || (key1 === "dark")) || (key1 === "source"))){ -const err9 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err10 = {instancePath:instancePath+"/themes/" + i0+"/id",schemaPath:"#/properties/themes/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err11 = {instancePath:instancePath+"/themes/" + i0+"/name",schemaPath:"#/properties/themes/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.dark !== undefined){ -if(typeof data1.dark !== "boolean"){ -const err12 = {instancePath:instancePath+"/themes/" + i0+"/dark",schemaPath:"#/properties/themes/items/properties/dark/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err13 = {instancePath:instancePath+"/themes/" + i0+"/source",schemaPath:"#/properties/themes/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.errors !== undefined){ -let data6 = data.errors; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err15 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: schema36.properties.errors.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -let data7 = data6[i1]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.file === undefined){ -const err16 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/required",keyword:"required",params:{missingProperty: "file"},message:"must have required property '"+"file"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.message === undefined){ -const err17 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key2 in data7){ -if(!((key2 === "file") || (key2 === "message"))){ -const err18 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data7.file !== undefined){ -if(typeof data7.file !== "string"){ -const err19 = {instancePath:instancePath+"/errors/" + i1+"/file",schemaPath:"#/properties/errors/items/properties/file/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data7.message !== undefined){ -if(typeof data7.message !== "string"){ -const err20 = {instancePath:instancePath+"/errors/" + i1+"/message",schemaPath:"#/properties/errors/items/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err22 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -validate35.errors = vErrors; -return errors === 0; -} - -export const CatalogRevision = validate36; -const schema37 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/CatalogRevision","$schema":"http://json-schema.org/draft-07/schema#","title":"CatalogRevision","required":["revision"],"additionalProperties":false}; - -function validate36(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CatalogRevision" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "revision")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate36.errors = vErrors; -return errors === 0; -} - -export const CheckpointParams = validate37; -const schema38 = {"type":"object","properties":{"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CheckpointParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CheckpointParams","additionalProperties":false}; - -function validate37(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CheckpointParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "reason")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err1 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate37.errors = vErrors; -return errors === 0; -} - -export const ClearHistoryParams = validate38; -const schema39 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ClearHistoryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ClearHistoryParams","additionalProperties":false}; - -function validate38(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ClearHistoryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "expected_revision")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err1 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema39.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate38.errors = vErrors; -return errors === 0; -} - -export const CommandParams = validate39; -const schema40 = {"type":"object","properties":{"command_id":{"type":"string"},"scope":{"type":"string"},"root_id":{"type":"string"},"operation":{"type":"string"},"payload":true},"$id":"https://whip.dev/protocol/v6/CommandParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandParams","required":["command_id","scope","operation"],"additionalProperties":false}; - -function validate39(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.scope === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.operation === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "command_id") || (key0 === "scope")) || (key0 === "root_id")) || (key0 === "operation")) || (key0 === "payload"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err4 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.scope !== undefined){ -if(typeof data.scope !== "string"){ -const err5 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err7 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate39.errors = vErrors; -return errors === 0; -} - -export const CommandResult = validate40; -const schema41 = {"type":"object","properties":{"content":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"operation":{"type":"string"},"result":true,"failure":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":false},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false},"command_id":{"type":"string"},"ingress_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CommandResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandResult","required":["operation","command_id","ingress_seq","status"],"additionalProperties":false}; - -function validate40(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.command_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.ingress_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "ingress_seq"},message:"must have required property '"+"ingress_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.status === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "content") || (key0 === "operation")) || (key0 === "result")) || (key0 === "failure")) || (key0 === "command_id")) || (key0 === "ingress_seq")) || (key0 === "status"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.content !== undefined){ -let data0 = data.content; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: schema41.properties.content.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err6 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.digest === undefined){ -const err7 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.size === undefined){ -const err8 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key1 in data0){ -if(!(((((key1 === "reference_id") || (key1 === "digest")) || (key1 === "size")) || (key1 === "media_type")) || (key1 === "source"))){ -const err9 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err10 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err11 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err12 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err13 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -else { -const err14 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err15 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err16 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err17 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.failure !== undefined){ -let data7 = data.failure; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err18 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/type",keyword:"type",params:{type: schema41.properties.failure.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.code === undefined){ -const err19 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.message === undefined){ -const err20 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key2 in data7){ -if(!(((key2 === "data") || (key2 === "code")) || (key2 === "message"))){ -const err21 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.data !== undefined){ -let data8 = data7.data; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err22 = {instancePath:instancePath+"/failure/data",schemaPath:"#/properties/failure/properties/data/type",keyword:"type",params:{type: schema41.properties.failure.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.kind === undefined){ -const err23 = {instancePath:instancePath+"/failure/data",schemaPath:"#/properties/failure/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -for(const key3 in data8){ -if(!(key3 === "kind")){ -const err24 = {instancePath:instancePath+"/failure/data",schemaPath:"#/properties/failure/properties/data/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data8.kind !== undefined){ -if(typeof data8.kind !== "string"){ -const err25 = {instancePath:instancePath+"/failure/data/kind",schemaPath:"#/properties/failure/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data7.code !== undefined){ -let data10 = data7.code; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err26 = {instancePath:instancePath+"/failure/code",schemaPath:"#/properties/failure/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data7.message !== undefined){ -if(typeof data7.message !== "string"){ -const err27 = {instancePath:instancePath+"/failure/message",schemaPath:"#/properties/failure/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err28 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data.ingress_seq !== undefined){ -let data13 = data.ingress_seq; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err29 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err30 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err32 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -validate40.errors = vErrors; -return errors === 0; -} - -export const CommandStatusParams = validate41; -const schema42 = {"type":"object","properties":{"command_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CommandStatusParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandStatusParams","required":["command_id"],"additionalProperties":false}; - -function validate41(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandStatusParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "command_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err2 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate41.errors = vErrors; -return errors === 0; -} - -export const CompactionListResult = validate42; -const schema43 = {"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"integer"},"cutoff":{"type":"integer"},"summary":{"type":"string"}},"required":["seq","cutoff","summary"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/CompactionListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionListResult"}; - -function validate42(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema43.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.seq === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.cutoff === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cutoff"},message:"must have required property '"+"cutoff"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.summary === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data0){ -if(!(((key0 === "seq") || (key0 === "cutoff")) || (key0 === "summary"))){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.seq !== undefined){ -let data1 = data0.seq; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err5 = {instancePath:instancePath+"/" + i0+"/seq",schemaPath:"#/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.cutoff !== undefined){ -let data2 = data0.cutoff; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err6 = {instancePath:instancePath+"/" + i0+"/cutoff",schemaPath:"#/items/properties/cutoff/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.summary !== undefined){ -if(typeof data0.summary !== "string"){ -const err7 = {instancePath:instancePath+"/" + i0+"/summary",schemaPath:"#/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -validate42.errors = vErrors; -return errors === 0; -} - -export const CompactionParams = validate43; -const schema44 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CompactionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionParams","additionalProperties":false}; - -function validate43(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((key0 === "model") || (key0 === "provider"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err1 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate43.errors = vErrors; -return errors === 0; -} - -export const CompactionResult = validate44; -const schema45 = {"type":"object","properties":{"cutoff":{"type":"integer"},"model":{"type":"string"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/CompactionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionResult","required":["cutoff","usage"],"additionalProperties":false}; - -function validate44(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cutoff === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cutoff"},message:"must have required property '"+"cutoff"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.usage === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "cutoff") || (key0 === "model")) || (key0 === "usage"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cutoff !== undefined){ -let data0 = data.cutoff; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err3 = {instancePath:instancePath+"/cutoff",schemaPath:"#/properties/cutoff/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err4 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.usage !== undefined){ -let data2 = data.usage; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.prompt_tokens === undefined){ -const err5 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2.completion_tokens === undefined){ -const err6 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key1 in data2){ -if(!((((((key1 === "reported") || (key1 === "cost")) || (key1 === "prompt_tokens")) || (key1 === "completion_tokens")) || (key1 === "prompt_tokens_details")) || (key1 === "completion_tokens_details"))){ -const err7 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data2.reported !== undefined){ -if(typeof data2.reported !== "boolean"){ -const err8 = {instancePath:instancePath+"/usage/reported",schemaPath:"#/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data2.cost !== undefined){ -let data4 = data2.cost; -if((data4 !== null) && (!(typeof data4 == "number"))){ -const err9 = {instancePath:instancePath+"/usage/cost",schemaPath:"#/properties/usage/properties/cost/type",keyword:"type",params:{type: schema45.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data2.prompt_tokens !== undefined){ -let data5 = data2.prompt_tokens; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err10 = {instancePath:instancePath+"/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data2.completion_tokens !== undefined){ -let data6 = data2.completion_tokens; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err11 = {instancePath:instancePath+"/usage/completion_tokens",schemaPath:"#/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data2.prompt_tokens_details !== undefined){ -let data7 = data2.prompt_tokens_details; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err12 = {instancePath:instancePath+"/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema45.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.cached_tokens === undefined){ -const err13 = {instancePath:instancePath+"/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key2 in data7){ -if(!(key2 === "cached_tokens")){ -const err14 = {instancePath:instancePath+"/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data7.cached_tokens !== undefined){ -let data8 = data7.cached_tokens; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err15 = {instancePath:instancePath+"/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data2.completion_tokens_details !== undefined){ -let data9 = data2.completion_tokens_details; -if((data9 !== null) && (!(data9 && typeof data9 == "object" && !Array.isArray(data9)))){ -const err16 = {instancePath:instancePath+"/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema45.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.reasoning_tokens === undefined){ -const err17 = {instancePath:instancePath+"/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key3 in data9){ -if(!(key3 === "reasoning_tokens")){ -const err18 = {instancePath:instancePath+"/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data9.reasoning_tokens !== undefined){ -let data10 = data9.reasoning_tokens; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err19 = {instancePath:instancePath+"/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -} -} -else { -const err20 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -validate44.errors = vErrors; -return errors === 0; -} - -export const CompactionRetryResult = validate45; -const schema46 = {"type":"object","properties":{"undone":{"type":"boolean"},"sequence":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/CompactionRetryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionRetryResult","required":["undone"],"additionalProperties":false}; - -function validate45(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionRetryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.undone === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "undone"},message:"must have required property '"+"undone"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "undone") || (key0 === "sequence"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.undone !== undefined){ -if(typeof data.undone !== "boolean"){ -const err2 = {instancePath:instancePath+"/undone",schemaPath:"#/properties/undone/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.sequence !== undefined){ -let data1 = data.sequence; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err3 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate45.errors = vErrors; -return errors === 0; -} - -export const CompactionSettingsResult = validate46; -const schema47 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"builtin_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CompactionSettingsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionSettingsResult","required":["builtin_default"],"additionalProperties":false}; - -function validate46(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionSettingsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.builtin_default === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "builtin_default"},message:"must have required property '"+"builtin_default"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "model") || (key0 === "provider")) || (key0 === "builtin_default"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err2 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err3 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.builtin_default !== undefined){ -if(typeof data.builtin_default !== "boolean"){ -const err4 = {instancePath:instancePath+"/builtin_default",schemaPath:"#/properties/builtin_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate46.errors = vErrors; -return errors === 0; -} - -export const CompletionParams = validate47; -const schema48 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"kind":{"type":"string"},"prefix":{"type":"string"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/CompletionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CompletionParams","required":["root_id","kind","prefix","limit"],"additionalProperties":false}; - -function validate47(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompletionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.kind === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.prefix === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "prefix"},message:"must have required property '"+"prefix"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "agent_id")) || (key0 === "kind")) || (key0 === "prefix")) || (key0 === "limit"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err6 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err7 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err8 = {instancePath:instancePath+"/prefix",schemaPath:"#/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err9 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate47.errors = vErrors; -return errors === 0; -} - -export const CompletionResult = validate48; -const schema49 = {"type":"object","properties":{"warnings":{"type":["null","array"],"items":{"type":"string"}},"candidates":{"type":["null","array"],"items":{"type":"object","properties":{"text":{"type":"string"},"description":{"type":"string"}},"required":["text","description"],"additionalProperties":false}},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CompletionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompletionResult","required":["candidates","truncated"],"additionalProperties":false}; - -function validate48(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompletionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.candidates === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "candidates"},message:"must have required property '"+"candidates"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.truncated === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "warnings") || (key0 === "candidates")) || (key0 === "truncated"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.warnings !== undefined){ -let data0 = data.warnings; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/warnings",schemaPath:"#/properties/warnings/type",keyword:"type",params:{type: schema49.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err4 = {instancePath:instancePath+"/warnings/" + i0,schemaPath:"#/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -if(data.candidates !== undefined){ -let data2 = data.candidates; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err5 = {instancePath:instancePath+"/candidates",schemaPath:"#/properties/candidates/type",keyword:"type",params:{type: schema49.properties.candidates.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data2)){ -const len1 = data2.length; -for(let i1=0; i1<len1; i1++){ -let data3 = data2[i1]; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.text === undefined){ -const err6 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data3.description === undefined){ -const err7 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data3){ -if(!((key1 === "text") || (key1 === "description"))){ -const err8 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data3.text !== undefined){ -if(typeof data3.text !== "string"){ -const err9 = {instancePath:instancePath+"/candidates/" + i1+"/text",schemaPath:"#/properties/candidates/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data3.description !== undefined){ -if(typeof data3.description !== "string"){ -const err10 = {instancePath:instancePath+"/candidates/" + i1+"/description",schemaPath:"#/properties/candidates/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err12 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate48.errors = vErrors; -return errors === 0; -} - -export const ComputerAppParams = validate49; -const schema50 = {"type":"object","properties":{"app":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ComputerAppParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ComputerAppParams","required":["app"],"additionalProperties":false}; - -function validate49(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ComputerAppParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.app === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "app"},message:"must have required property '"+"app"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "app")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.app !== undefined){ -if(typeof data.app !== "string"){ -const err2 = {instancePath:instancePath+"/app",schemaPath:"#/properties/app/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate49.errors = vErrors; -return errors === 0; -} - -export const ComputerStatusResult = validate50; -const schema51 = {"type":"object","properties":{"enabled":{"type":"boolean"},"default_deny":{"type":"boolean"},"allowed":{"type":["null","array"],"items":{"type":"string"}},"denied":{"type":["null","array"],"items":{"type":"string"}},"session_allowed":{"type":["null","array"],"items":{"type":"string"}},"session_denied":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ComputerStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ComputerStatusResult","required":["enabled","default_deny","allowed","denied","session_allowed","session_denied"],"additionalProperties":false}; - -function validate50(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ComputerStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.enabled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.default_deny === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_deny"},message:"must have required property '"+"default_deny"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.allowed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "allowed"},message:"must have required property '"+"allowed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.denied === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "denied"},message:"must have required property '"+"denied"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.session_allowed === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "session_allowed"},message:"must have required property '"+"session_allowed"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.session_denied === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "session_denied"},message:"must have required property '"+"session_denied"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "enabled") || (key0 === "default_deny")) || (key0 === "allowed")) || (key0 === "denied")) || (key0 === "session_allowed")) || (key0 === "session_denied"))){ -const err6 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err7 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.default_deny !== undefined){ -if(typeof data.default_deny !== "boolean"){ -const err8 = {instancePath:instancePath+"/default_deny",schemaPath:"#/properties/default_deny/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.allowed !== undefined){ -let data2 = data.allowed; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err9 = {instancePath:instancePath+"/allowed",schemaPath:"#/properties/allowed/type",keyword:"type",params:{type: schema51.properties.allowed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err10 = {instancePath:instancePath+"/allowed/" + i0,schemaPath:"#/properties/allowed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data.denied !== undefined){ -let data4 = data.denied; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err11 = {instancePath:instancePath+"/denied",schemaPath:"#/properties/denied/type",keyword:"type",params:{type: schema51.properties.denied.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data4[i1] !== "string"){ -const err12 = {instancePath:instancePath+"/denied/" + i1,schemaPath:"#/properties/denied/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.session_allowed !== undefined){ -let data6 = data.session_allowed; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err13 = {instancePath:instancePath+"/session_allowed",schemaPath:"#/properties/session_allowed/type",keyword:"type",params:{type: schema51.properties.session_allowed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(Array.isArray(data6)){ -const len2 = data6.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data6[i2] !== "string"){ -const err14 = {instancePath:instancePath+"/session_allowed/" + i2,schemaPath:"#/properties/session_allowed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.session_denied !== undefined){ -let data8 = data.session_denied; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err15 = {instancePath:instancePath+"/session_denied",schemaPath:"#/properties/session_denied/type",keyword:"type",params:{type: schema51.properties.session_denied.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data8)){ -const len3 = data8.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data8[i3] !== "string"){ -const err16 = {instancePath:instancePath+"/session_denied/" + i3,schemaPath:"#/properties/session_denied/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate50.errors = vErrors; -return errors === 0; -} - -export const ConfigurationUpdate = validate51; -const schema52 = {"type":"object","properties":{"default_execution_engine":{"type":["null","string"]},"disabled_providers":{"type":["null","array"],"items":{"type":"string"}},"remote_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"runtime_id":{"type":"string"},"connect_on_launch":{"type":"boolean"}},"required":["id","name","url","runtime_id","connect_on_launch"],"additionalProperties":false}},"import_claude":{"type":["null","boolean"]},"import_codex":{"type":["null","boolean"]},"brand_icons":{"type":["null","boolean"]},"revision":{"type":"string"},"default_model":{"type":["null","string"]},"default_provider":{"type":["null","string"]},"default_effort":{"type":["null","string"]},"default_permission_mode":{"type":["null","string"]},"compact_model":{"type":["null","string"]},"compact_provider":{"type":["null","string"]},"compact_percent":{"type":["null","integer"]},"goal_max_rounds":{"type":["null","integer"]},"max_retries":{"type":["null","integer"]}},"$id":"https://whip.dev/protocol/v6/ConfigurationUpdate","$schema":"http://json-schema.org/draft-07/schema#","title":"ConfigurationUpdate","required":["revision"],"additionalProperties":false}; - -function validate51(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ConfigurationUpdate" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema52.properties, key0))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.default_execution_engine !== undefined){ -let data0 = data.default_execution_engine; -if((data0 !== null) && (typeof data0 !== "string")){ -const err2 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: schema52.properties.default_execution_engine.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.disabled_providers !== undefined){ -let data1 = data.disabled_providers; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err3 = {instancePath:instancePath+"/disabled_providers",schemaPath:"#/properties/disabled_providers/type",keyword:"type",params:{type: schema52.properties.disabled_providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err4 = {instancePath:instancePath+"/disabled_providers/" + i0,schemaPath:"#/properties/disabled_providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -if(data.remote_hosts !== undefined){ -let data3 = data.remote_hosts; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err5 = {instancePath:instancePath+"/remote_hosts",schemaPath:"#/properties/remote_hosts/type",keyword:"type",params:{type: schema52.properties.remote_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data3)){ -const len1 = data3.length; -for(let i1=0; i1<len1; i1++){ -let data4 = data3[i1]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.id === undefined){ -const err6 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data4.name === undefined){ -const err7 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4.url === undefined){ -const err8 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.runtime_id === undefined){ -const err9 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.connect_on_launch === undefined){ -const err10 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "connect_on_launch"},message:"must have required property '"+"connect_on_launch"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -for(const key1 in data4){ -if(!(((((key1 === "id") || (key1 === "name")) || (key1 === "url")) || (key1 === "runtime_id")) || (key1 === "connect_on_launch"))){ -const err11 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data4.id !== undefined){ -if(typeof data4.id !== "string"){ -const err12 = {instancePath:instancePath+"/remote_hosts/" + i1+"/id",schemaPath:"#/properties/remote_hosts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err13 = {instancePath:instancePath+"/remote_hosts/" + i1+"/name",schemaPath:"#/properties/remote_hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data4.url !== undefined){ -if(typeof data4.url !== "string"){ -const err14 = {instancePath:instancePath+"/remote_hosts/" + i1+"/url",schemaPath:"#/properties/remote_hosts/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data4.runtime_id !== undefined){ -if(typeof data4.runtime_id !== "string"){ -const err15 = {instancePath:instancePath+"/remote_hosts/" + i1+"/runtime_id",schemaPath:"#/properties/remote_hosts/items/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data4.connect_on_launch !== undefined){ -if(typeof data4.connect_on_launch !== "boolean"){ -const err16 = {instancePath:instancePath+"/remote_hosts/" + i1+"/connect_on_launch",schemaPath:"#/properties/remote_hosts/items/properties/connect_on_launch/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.import_claude !== undefined){ -let data10 = data.import_claude; -if((data10 !== null) && (typeof data10 !== "boolean")){ -const err18 = {instancePath:instancePath+"/import_claude",schemaPath:"#/properties/import_claude/type",keyword:"type",params:{type: schema52.properties.import_claude.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.import_codex !== undefined){ -let data11 = data.import_codex; -if((data11 !== null) && (typeof data11 !== "boolean")){ -const err19 = {instancePath:instancePath+"/import_codex",schemaPath:"#/properties/import_codex/type",keyword:"type",params:{type: schema52.properties.import_codex.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.brand_icons !== undefined){ -let data12 = data.brand_icons; -if((data12 !== null) && (typeof data12 !== "boolean")){ -const err20 = {instancePath:instancePath+"/brand_icons",schemaPath:"#/properties/brand_icons/type",keyword:"type",params:{type: schema52.properties.brand_icons.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err21 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.default_model !== undefined){ -let data14 = data.default_model; -if((data14 !== null) && (typeof data14 !== "string")){ -const err22 = {instancePath:instancePath+"/default_model",schemaPath:"#/properties/default_model/type",keyword:"type",params:{type: schema52.properties.default_model.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.default_provider !== undefined){ -let data15 = data.default_provider; -if((data15 !== null) && (typeof data15 !== "string")){ -const err23 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: schema52.properties.default_provider.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.default_effort !== undefined){ -let data16 = data.default_effort; -if((data16 !== null) && (typeof data16 !== "string")){ -const err24 = {instancePath:instancePath+"/default_effort",schemaPath:"#/properties/default_effort/type",keyword:"type",params:{type: schema52.properties.default_effort.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.default_permission_mode !== undefined){ -let data17 = data.default_permission_mode; -if((data17 !== null) && (typeof data17 !== "string")){ -const err25 = {instancePath:instancePath+"/default_permission_mode",schemaPath:"#/properties/default_permission_mode/type",keyword:"type",params:{type: schema52.properties.default_permission_mode.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data.compact_model !== undefined){ -let data18 = data.compact_model; -if((data18 !== null) && (typeof data18 !== "string")){ -const err26 = {instancePath:instancePath+"/compact_model",schemaPath:"#/properties/compact_model/type",keyword:"type",params:{type: schema52.properties.compact_model.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data.compact_provider !== undefined){ -let data19 = data.compact_provider; -if((data19 !== null) && (typeof data19 !== "string")){ -const err27 = {instancePath:instancePath+"/compact_provider",schemaPath:"#/properties/compact_provider/type",keyword:"type",params:{type: schema52.properties.compact_provider.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.compact_percent !== undefined){ -let data20 = data.compact_percent; -if((data20 !== null) && (!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20))))){ -const err28 = {instancePath:instancePath+"/compact_percent",schemaPath:"#/properties/compact_percent/type",keyword:"type",params:{type: schema52.properties.compact_percent.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data.goal_max_rounds !== undefined){ -let data21 = data.goal_max_rounds; -if((data21 !== null) && (!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21))))){ -const err29 = {instancePath:instancePath+"/goal_max_rounds",schemaPath:"#/properties/goal_max_rounds/type",keyword:"type",params:{type: schema52.properties.goal_max_rounds.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data.max_retries !== undefined){ -let data22 = data.max_retries; -if((data22 !== null) && (!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22))))){ -const err30 = {instancePath:instancePath+"/max_retries",schemaPath:"#/properties/max_retries/type",keyword:"type",params:{type: schema52.properties.max_retries.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -else { -const err31 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -validate51.errors = vErrors; -return errors === 0; -} - -export const ContentEventPayload = validate52; -const schema53 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false}},"required":["used","size","usage"],"additionalProperties":false},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"truncated":{"type":"boolean","const":true}},"$id":"https://whip.dev/protocol/v6/ContentEventPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentEventPayload","required":["content","truncated"],"additionalProperties":false}; - -function validate52(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentEventPayload" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.content === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.truncated === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema53.properties, key0))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.part_id !== undefined){ -if(typeof data.part_id !== "string"){ -const err3 = {instancePath:instancePath+"/part_id",schemaPath:"#/properties/part_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.display !== undefined){ -let data1 = data.display; -if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err4 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema53.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key1 in data1){ -if(!(((((key1 === "target") || (key1 === "command")) || (key1 === "query")) || (key1 === "child_id")) || (key1 === "label"))){ -const err5 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.target !== undefined){ -if(typeof data1.target !== "string"){ -const err6 = {instancePath:instancePath+"/display/target",schemaPath:"#/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.command !== undefined){ -if(typeof data1.command !== "string"){ -const err7 = {instancePath:instancePath+"/display/command",schemaPath:"#/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.query !== undefined){ -if(typeof data1.query !== "string"){ -const err8 = {instancePath:instancePath+"/display/query",schemaPath:"#/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.child_id !== undefined){ -if(typeof data1.child_id !== "string"){ -const err9 = {instancePath:instancePath+"/display/child_id",schemaPath:"#/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err10 = {instancePath:instancePath+"/display/label",schemaPath:"#/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data7 = data.accounting; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema53.properties.accounting.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.root_id === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7.agent_id === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.scope === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.revision === undefined){ -const err15 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7.reported_cost_micros === undefined){ -const err16 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.estimated_cost_micros === undefined){ -const err17 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.reported_cost_calls === undefined){ -const err18 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.estimated_cost_calls === undefined){ -const err19 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.unknown_cost_calls === undefined){ -const err20 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data7.reported_calls === undefined){ -const err21 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data7.estimated_calls === undefined){ -const err22 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data7.pending_calls === undefined){ -const err23 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -for(const key2 in data7){ -if(!(func2.call(schema53.properties.accounting.properties, key2))){ -const err24 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err25 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err26 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data7.scope !== undefined){ -if(typeof data7.scope !== "string"){ -const err27 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data7.revision !== undefined){ -let data11 = data7.revision; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err28 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err29 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -else { -const err30 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data7.reported_cost_micros !== undefined){ -let data12 = data7.reported_cost_micros; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err31 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err32 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -else { -const err33 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data7.estimated_cost_micros !== undefined){ -let data13 = data7.estimated_cost_micros; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err34 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err35 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -else { -const err36 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data7.reported_cost_calls !== undefined){ -let data14 = data7.reported_cost_calls; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err37 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err38 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -else { -const err39 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data7.estimated_cost_calls !== undefined){ -let data15 = data7.estimated_cost_calls; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err40 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err41 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data7.unknown_cost_calls !== undefined){ -let data16 = data7.unknown_cost_calls; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err43 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err44 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data7.reported_calls !== undefined){ -let data17 = data7.reported_calls; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err46 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err47 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -else { -const err48 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data7.estimated_calls !== undefined){ -let data18 = data7.estimated_calls; -if(typeof data18 === "string"){ -if(!pattern0.test(data18)){ -const err49 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(!(formats0.validate(data18))){ -const err50 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -else { -const err51 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data7.pending_calls !== undefined){ -let data19 = data7.pending_calls; -if(typeof data19 === "string"){ -if(!pattern0.test(data19)){ -const err52 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(!(formats0.validate(data19))){ -const err53 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -else { -const err54 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -} -} -if(data.usage !== undefined){ -let data20 = data.usage; -if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err55 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema53.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.used === undefined){ -const err56 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data20.size === undefined){ -const err57 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data20.usage === undefined){ -const err58 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -for(const key3 in data20){ -if(!(((key3 === "used") || (key3 === "size")) || (key3 === "usage"))){ -const err59 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data20.used !== undefined){ -let data21 = data20.used; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err60 = {instancePath:instancePath+"/usage/used",schemaPath:"#/properties/usage/properties/used/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data20.size !== undefined){ -let data22 = data20.size; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err61 = {instancePath:instancePath+"/usage/size",schemaPath:"#/properties/usage/properties/size/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data20.usage !== undefined){ -let data23 = data20.usage; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt_tokens === undefined){ -const err62 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data23.completion_tokens === undefined){ -const err63 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -for(const key4 in data23){ -if(!((((((key4 === "reported") || (key4 === "cost")) || (key4 === "prompt_tokens")) || (key4 === "completion_tokens")) || (key4 === "prompt_tokens_details")) || (key4 === "completion_tokens_details"))){ -const err64 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data23.reported !== undefined){ -if(typeof data23.reported !== "boolean"){ -const err65 = {instancePath:instancePath+"/usage/usage/reported",schemaPath:"#/properties/usage/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data23.cost !== undefined){ -let data25 = data23.cost; -if((data25 !== null) && (!(typeof data25 == "number"))){ -const err66 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data23.prompt_tokens !== undefined){ -let data26 = data23.prompt_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err67 = {instancePath:instancePath+"/usage/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data23.completion_tokens !== undefined){ -let data27 = data23.completion_tokens; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err68 = {instancePath:instancePath+"/usage/usage/completion_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data23.prompt_tokens_details !== undefined){ -let data28 = data23.prompt_tokens_details; -if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err69 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data28 && typeof data28 == "object" && !Array.isArray(data28)){ -if(data28.cached_tokens === undefined){ -const err70 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -for(const key5 in data28){ -if(!(key5 === "cached_tokens")){ -const err71 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data28.cached_tokens !== undefined){ -let data29 = data28.cached_tokens; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err72 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -} -if(data23.completion_tokens_details !== undefined){ -let data30 = data23.completion_tokens_details; -if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err73 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.reasoning_tokens === undefined){ -const err74 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -for(const key6 in data30){ -if(!(key6 === "reasoning_tokens")){ -const err75 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data30.reasoning_tokens !== undefined){ -let data31 = data30.reasoning_tokens; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err76 = {instancePath:instancePath+"/usage/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -} -} -} -else { -const err77 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err78 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err79 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err80 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err81 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data.host_status !== undefined){ -if(typeof data.host_status !== "string"){ -const err82 = {instancePath:instancePath+"/host_status",schemaPath:"#/properties/host_status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err83 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err84 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err85 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data.args !== undefined){ -if(typeof data.args !== "string"){ -const err86 = {instancePath:instancePath+"/args",schemaPath:"#/properties/args/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data.result !== undefined){ -if(typeof data.result !== "string"){ -const err87 = {instancePath:instancePath+"/result",schemaPath:"#/properties/result/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data.content !== undefined){ -let data42 = data.content; -if(data42 && typeof data42 == "object" && !Array.isArray(data42)){ -if(data42.reference_id === undefined){ -const err88 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(data42.digest === undefined){ -const err89 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(data42.size === undefined){ -const err90 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -for(const key7 in data42){ -if(!(((((key7 === "reference_id") || (key7 === "digest")) || (key7 === "size")) || (key7 === "media_type")) || (key7 === "source"))){ -const err91 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data42.reference_id !== undefined){ -if(typeof data42.reference_id !== "string"){ -const err92 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data42.digest !== undefined){ -if(typeof data42.digest !== "string"){ -const err93 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data42.size !== undefined){ -let data45 = data42.size; -if(typeof data45 === "string"){ -if(!pattern0.test(data45)){ -const err94 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(!(formats0.validate(data45))){ -const err95 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -else { -const err96 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data42.media_type !== undefined){ -if(typeof data42.media_type !== "string"){ -const err97 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data42.source !== undefined){ -if(typeof data42.source !== "string"){ -const err98 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -else { -const err99 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data.truncated !== undefined){ -let data48 = data.truncated; -if(typeof data48 !== "boolean"){ -const err100 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -if(true !== data48){ -const err101 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/const",keyword:"const",params:{allowedValue: true},message:"must be equal to constant"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -} -else { -const err102 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -validate52.errors = vErrors; -return errors === 0; -} - -export const ContentHandle = validate53; -const schema54 = {"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ContentHandle","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentHandle","required":["reference_id","digest","size"],"additionalProperties":false}; - -function validate53(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentHandle" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.reference_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.digest === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.size === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "reference_id") || (key0 === "digest")) || (key0 === "size")) || (key0 === "media_type")) || (key0 === "source"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.reference_id !== undefined){ -if(typeof data.reference_id !== "string"){ -const err4 = {instancePath:instancePath+"/reference_id",schemaPath:"#/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.digest !== undefined){ -if(typeof data.digest !== "string"){ -const err5 = {instancePath:instancePath+"/digest",schemaPath:"#/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.size !== undefined){ -let data2 = data.size; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err6 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err7 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.media_type !== undefined){ -if(typeof data.media_type !== "string"){ -const err9 = {instancePath:instancePath+"/media_type",schemaPath:"#/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err10 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate53.errors = vErrors; -return errors === 0; -} - -export const ContentReadParams = validate54; -const schema55 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"reference_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ContentReadParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentReadParams","required":["root_id","reference_id","offset","limit"],"additionalProperties":false}; - -function validate54(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentReadParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.reference_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.offset === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "agent_id")) || (key0 === "reference_id")) || (key0 === "offset")) || (key0 === "limit"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err6 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.reference_id !== undefined){ -if(typeof data.reference_id !== "string"){ -const err7 = {instancePath:instancePath+"/reference_id",schemaPath:"#/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.offset !== undefined){ -let data3 = data.offset; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err8 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err9 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err11 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate54.errors = vErrors; -return errors === 0; -} - -export const ContentReadResult = validate55; -const schema56 = {"type":"object","properties":{"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/ContentReadResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentReadResult","required":["data","content"],"additionalProperties":false}; -const pattern52 = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", "u"); - -function validate55(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentReadResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.data === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "data"},message:"must have required property '"+"data"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.content === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "data") || (key0 === "content"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.data !== undefined){ -let data0 = data.data; -if((typeof data0 !== "string") && (data0 !== null)){ -const err3 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema56.properties.data.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern52.test(data0)){ -const err4 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -if(data.content !== undefined){ -let data1 = data.content; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.reference_id === undefined){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.digest === undefined){ -const err6 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.size === undefined){ -const err7 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data1){ -if(!(((((key1 === "reference_id") || (key1 === "digest")) || (key1 === "size")) || (key1 === "media_type")) || (key1 === "source"))){ -const err8 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.reference_id !== undefined){ -if(typeof data1.reference_id !== "string"){ -const err9 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.digest !== undefined){ -if(typeof data1.digest !== "string"){ -const err10 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.size !== undefined){ -let data4 = data1.size; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err11 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err12 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -else { -const err13 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.media_type !== undefined){ -if(typeof data1.media_type !== "string"){ -const err14 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err15 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate55.errors = vErrors; -return errors === 0; -} - -export const ContextAuditResult = validate56; -const schema57 = {"type":"object","properties":{"working_directory":{"type":"string"},"rows":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"bytes":{"type":"integer"},"note":{"type":"string"}},"required":["label"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/ContextAuditResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ContextAuditResult","required":["working_directory","rows"],"additionalProperties":false}; - -function validate56(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContextAuditResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.working_directory === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "working_directory"},message:"must have required property '"+"working_directory"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.rows === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "working_directory") || (key0 === "rows"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.working_directory !== undefined){ -if(typeof data.working_directory !== "string"){ -const err3 = {instancePath:instancePath+"/working_directory",schemaPath:"#/properties/working_directory/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.rows !== undefined){ -let data1 = data.rows; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err4 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: schema57.properties.rows.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.label === undefined){ -const err5 = {instancePath:instancePath+"/rows/" + i0,schemaPath:"#/properties/rows/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key1 in data2){ -if(!(((key1 === "label") || (key1 === "bytes")) || (key1 === "note"))){ -const err6 = {instancePath:instancePath+"/rows/" + i0,schemaPath:"#/properties/rows/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data2.label !== undefined){ -if(typeof data2.label !== "string"){ -const err7 = {instancePath:instancePath+"/rows/" + i0+"/label",schemaPath:"#/properties/rows/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data2.bytes !== undefined){ -let data4 = data2.bytes; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err8 = {instancePath:instancePath+"/rows/" + i0+"/bytes",schemaPath:"#/properties/rows/items/properties/bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data2.note !== undefined){ -if(typeof data2.note !== "string"){ -const err9 = {instancePath:instancePath+"/rows/" + i0+"/note",schemaPath:"#/properties/rows/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/rows/" + i0,schemaPath:"#/properties/rows/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate56.errors = vErrors; -return errors === 0; -} - -export const CreateSessionParams = validate57; -const schema58 = {"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"kind":{"type":"string"},"cwd":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"permission_mode":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CreateSessionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CreateSessionParams","required":["kind","cwd","model","provider"],"additionalProperties":false}; - -function validate57(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CreateSessionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.kind === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cwd === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.model === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.provider === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((((((key0 === "execution_engine") || (key0 === "definition")) || (key0 === "kind")) || (key0 === "cwd")) || (key0 === "model")) || (key0 === "provider")) || (key0 === "effort")) || (key0 === "permission_mode"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.execution_engine !== undefined){ -if(typeof data.execution_engine !== "string"){ -const err5 = {instancePath:instancePath+"/execution_engine",schemaPath:"#/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err7 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err8 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err9 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err10 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err11 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err12 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate57.errors = vErrors; -return errors === 0; -} - -export const DefinitionList = validate58; -const schema59 = {"type":"object","properties":{"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"},"built_in":{"type":"boolean"},"registered_by":{"type":"string"},"created_at":{"type":"string"}},"required":["id","revision","built_in","registered_by","created_at"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/DefinitionList","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionList","required":["items"],"additionalProperties":false}; - -function validate58(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "items")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.items !== undefined){ -let data0 = data.items; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema59.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err3 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.revision === undefined){ -const err4 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.built_in === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "built_in"},message:"must have required property '"+"built_in"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.registered_by === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "registered_by"},message:"must have required property '"+"registered_by"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.created_at === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data1){ -if(!(((((key1 === "id") || (key1 === "revision")) || (key1 === "built_in")) || (key1 === "registered_by")) || (key1 === "created_at"))){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err9 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.revision !== undefined){ -if(typeof data1.revision !== "string"){ -const err10 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.built_in !== undefined){ -if(typeof data1.built_in !== "boolean"){ -const err11 = {instancePath:instancePath+"/items/" + i0+"/built_in",schemaPath:"#/properties/items/items/properties/built_in/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.registered_by !== undefined){ -if(typeof data1.registered_by !== "string"){ -const err12 = {instancePath:instancePath+"/items/" + i0+"/registered_by",schemaPath:"#/properties/items/items/properties/registered_by/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.created_at !== undefined){ -if(typeof data1.created_at !== "string"){ -const err13 = {instancePath:instancePath+"/items/" + i0+"/created_at",schemaPath:"#/properties/items/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -} -else { -const err15 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -validate58.errors = vErrors; -return errors === 0; -} - -export const DefinitionParams = validate59; -const schema60 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/DefinitionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionParams","required":["id"],"additionalProperties":false}; - -function validate59(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "revision"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate59.errors = vErrors; -return errors === 0; -} - -export const DefinitionRecord = validate60; -const schema61 = {"type":"object","properties":{"definition":{"type":"object","properties":{"id":{"type":"string"},"instructions":{"type":"object","properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":false},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":false},"compaction":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"threshold":{"type":"number"}},"required":["model","provider","threshold"],"additionalProperties":false},"mcp":{"type":"object","properties":{"servers":{"type":["null","array"],"items":{"type":"string"}}},"required":["servers"],"additionalProperties":false},"tools":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"input_schema":true,"output_schema":true,"timeout_millis":{"type":"integer"}},"required":["name","description","input_schema","output_schema","timeout_millis"],"additionalProperties":false}},"output":true,"children":{"type":"object","additionalProperties":{"type":"object","properties":{"instructions":{"type":["null","object"],"properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":false},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":false},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"output":true},"required":["instructions","modules","capabilities","tools","model","budgets","report","output"],"additionalProperties":false}},"surface":{"type":"object","properties":{"auto_title":{"type":"boolean"},"goal_loop":{"type":"boolean"}},"required":["auto_title","goal_loop"],"additionalProperties":false},"hooks":{"type":["null","object"],"properties":{"before_tool":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false},"before_spawn":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false},"turn_start":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false}},"required":["before_tool","before_spawn","turn_start"],"additionalProperties":false}},"required":["id","instructions","modules","capabilities","model","compaction","mcp","tools","output","children","surface","hooks"],"additionalProperties":false},"revision":{"type":"string"},"built_in":{"type":"boolean"},"registered_by":{"type":"string"},"created_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/DefinitionRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRecord","required":["definition","revision","built_in","registered_by","created_at"],"additionalProperties":false}; - -function validate60(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.built_in === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "built_in"},message:"must have required property '"+"built_in"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.registered_by === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "registered_by"},message:"must have required property '"+"registered_by"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.created_at === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "definition") || (key0 === "revision")) || (key0 === "built_in")) || (key0 === "registered_by")) || (key0 === "created_at"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.definition !== undefined){ -let data0 = data.definition; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.instructions === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.modules === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.capabilities === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.model === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.compaction === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "compaction"},message:"must have required property '"+"compaction"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.mcp === undefined){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.tools === undefined){ -const err13 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.output === undefined){ -const err14 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.children === undefined){ -const err15 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "children"},message:"must have required property '"+"children"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.surface === undefined){ -const err16 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data0.hooks === undefined){ -const err17 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "hooks"},message:"must have required property '"+"hooks"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key1 in data0){ -if(!(func2.call(schema61.properties.definition.properties, key1))){ -const err18 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err19 = {instancePath:instancePath+"/definition/id",schemaPath:"#/properties/definition/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data0.instructions !== undefined){ -let data2 = data0.instructions; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.persona === undefined){ -const err20 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.rules === undefined){ -const err21 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data2.project_files === undefined){ -const err22 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data2.skill_discovery === undefined){ -const err23 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data2.standing_instructions === undefined){ -const err24 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -for(const key2 in data2){ -if(!(((((key2 === "persona") || (key2 === "rules")) || (key2 === "project_files")) || (key2 === "skill_discovery")) || (key2 === "standing_instructions"))){ -const err25 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.persona !== undefined){ -if(typeof data2.persona !== "string"){ -const err26 = {instancePath:instancePath+"/definition/instructions/persona",schemaPath:"#/properties/definition/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.rules !== undefined){ -if(typeof data2.rules !== "string"){ -const err27 = {instancePath:instancePath+"/definition/instructions/rules",schemaPath:"#/properties/definition/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.project_files !== undefined){ -let data5 = data2.project_files; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err28 = {instancePath:instancePath+"/definition/instructions/project_files",schemaPath:"#/properties/definition/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema61.properties.definition.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data5[i0] !== "string"){ -const err29 = {instancePath:instancePath+"/definition/instructions/project_files/" + i0,schemaPath:"#/properties/definition/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -} -if(data2.skill_discovery !== undefined){ -if(typeof data2.skill_discovery !== "boolean"){ -const err30 = {instancePath:instancePath+"/definition/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data2.standing_instructions !== undefined){ -if(typeof data2.standing_instructions !== "boolean"){ -const err31 = {instancePath:instancePath+"/definition/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -else { -const err32 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data0.modules !== undefined){ -let data9 = data0.modules; -if((data9 !== null) && (!(Array.isArray(data9)))){ -const err33 = {instancePath:instancePath+"/definition/modules",schemaPath:"#/properties/definition/properties/modules/type",keyword:"type",params:{type: schema61.properties.definition.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(Array.isArray(data9)){ -const len1 = data9.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data9[i1] !== "string"){ -const err34 = {instancePath:instancePath+"/definition/modules/" + i1,schemaPath:"#/properties/definition/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -} -if(data0.capabilities !== undefined){ -let data11 = data0.capabilities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err35 = {instancePath:instancePath+"/definition/capabilities",schemaPath:"#/properties/definition/properties/capabilities/type",keyword:"type",params:{type: schema61.properties.definition.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err36 = {instancePath:instancePath+"/definition/capabilities/" + i2,schemaPath:"#/properties/definition/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -} -if(data0.model !== undefined){ -let data13 = data0.model; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.model === undefined){ -const err37 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data13.provider === undefined){ -const err38 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data13.effort === undefined){ -const err39 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -for(const key3 in data13){ -if(!(((key3 === "model") || (key3 === "provider")) || (key3 === "effort"))){ -const err40 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data13.model !== undefined){ -if(typeof data13.model !== "string"){ -const err41 = {instancePath:instancePath+"/definition/model/model",schemaPath:"#/properties/definition/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data13.provider !== undefined){ -if(typeof data13.provider !== "string"){ -const err42 = {instancePath:instancePath+"/definition/model/provider",schemaPath:"#/properties/definition/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data13.effort !== undefined){ -if(typeof data13.effort !== "string"){ -const err43 = {instancePath:instancePath+"/definition/model/effort",schemaPath:"#/properties/definition/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -else { -const err44 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data0.compaction !== undefined){ -let data17 = data0.compaction; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.model === undefined){ -const err45 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data17.provider === undefined){ -const err46 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data17.threshold === undefined){ -const err47 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "threshold"},message:"must have required property '"+"threshold"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -for(const key4 in data17){ -if(!(((key4 === "model") || (key4 === "provider")) || (key4 === "threshold"))){ -const err48 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data17.model !== undefined){ -if(typeof data17.model !== "string"){ -const err49 = {instancePath:instancePath+"/definition/compaction/model",schemaPath:"#/properties/definition/properties/compaction/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data17.provider !== undefined){ -if(typeof data17.provider !== "string"){ -const err50 = {instancePath:instancePath+"/definition/compaction/provider",schemaPath:"#/properties/definition/properties/compaction/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data17.threshold !== undefined){ -if(!(typeof data17.threshold == "number")){ -const err51 = {instancePath:instancePath+"/definition/compaction/threshold",schemaPath:"#/properties/definition/properties/compaction/properties/threshold/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -else { -const err52 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data0.mcp !== undefined){ -let data21 = data0.mcp; -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.servers === undefined){ -const err53 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -for(const key5 in data21){ -if(!(key5 === "servers")){ -const err54 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data21.servers !== undefined){ -let data22 = data21.servers; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err55 = {instancePath:instancePath+"/definition/mcp/servers",schemaPath:"#/properties/definition/properties/mcp/properties/servers/type",keyword:"type",params:{type: schema61.properties.definition.properties.mcp.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(Array.isArray(data22)){ -const len3 = data22.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data22[i3] !== "string"){ -const err56 = {instancePath:instancePath+"/definition/mcp/servers/" + i3,schemaPath:"#/properties/definition/properties/mcp/properties/servers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -} -} -} -else { -const err57 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data24 = data0.tools; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err58 = {instancePath:instancePath+"/definition/tools",schemaPath:"#/properties/definition/properties/tools/type",keyword:"type",params:{type: schema61.properties.definition.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(Array.isArray(data24)){ -const len4 = data24.length; -for(let i4=0; i4<len4; i4++){ -let data25 = data24[i4]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.name === undefined){ -const err59 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data25.description === undefined){ -const err60 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data25.input_schema === undefined){ -const err61 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "input_schema"},message:"must have required property '"+"input_schema"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data25.output_schema === undefined){ -const err62 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "output_schema"},message:"must have required property '"+"output_schema"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data25.timeout_millis === undefined){ -const err63 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -for(const key6 in data25){ -if(!(((((key6 === "name") || (key6 === "description")) || (key6 === "input_schema")) || (key6 === "output_schema")) || (key6 === "timeout_millis"))){ -const err64 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data25.name !== undefined){ -if(typeof data25.name !== "string"){ -const err65 = {instancePath:instancePath+"/definition/tools/" + i4+"/name",schemaPath:"#/properties/definition/properties/tools/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data25.description !== undefined){ -if(typeof data25.description !== "string"){ -const err66 = {instancePath:instancePath+"/definition/tools/" + i4+"/description",schemaPath:"#/properties/definition/properties/tools/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data25.timeout_millis !== undefined){ -let data28 = data25.timeout_millis; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err67 = {instancePath:instancePath+"/definition/tools/" + i4+"/timeout_millis",schemaPath:"#/properties/definition/properties/tools/items/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -else { -const err68 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -if(data0.children !== undefined){ -let data29 = data0.children; -if(data29 && typeof data29 == "object" && !Array.isArray(data29)){ -for(const key7 in data29){ -let data30 = data29[key7]; -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.instructions === undefined){ -const err69 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data30.modules === undefined){ -const err70 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data30.capabilities === undefined){ -const err71 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data30.tools === undefined){ -const err72 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(data30.model === undefined){ -const err73 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(data30.budgets === undefined){ -const err74 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(data30.report === undefined){ -const err75 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(data30.output === undefined){ -const err76 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -for(const key8 in data30){ -if(!((((((((key8 === "instructions") || (key8 === "modules")) || (key8 === "capabilities")) || (key8 === "tools")) || (key8 === "model")) || (key8 === "budgets")) || (key8 === "report")) || (key8 === "output"))){ -const err77 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data30.instructions !== undefined){ -let data31 = data30.instructions; -if((data31 !== null) && (!(data31 && typeof data31 == "object" && !Array.isArray(data31)))){ -const err78 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.instructions.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -if(data31.persona === undefined){ -const err79 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data31.rules === undefined){ -const err80 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(data31.project_files === undefined){ -const err81 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data31.skill_discovery === undefined){ -const err82 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data31.standing_instructions === undefined){ -const err83 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -for(const key9 in data31){ -if(!(((((key9 === "persona") || (key9 === "rules")) || (key9 === "project_files")) || (key9 === "skill_discovery")) || (key9 === "standing_instructions"))){ -const err84 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data31.persona !== undefined){ -if(typeof data31.persona !== "string"){ -const err85 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/persona",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data31.rules !== undefined){ -if(typeof data31.rules !== "string"){ -const err86 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/rules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data31.project_files !== undefined){ -let data34 = data31.project_files; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err87 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(Array.isArray(data34)){ -const len5 = data34.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data34[i5] !== "string"){ -const err88 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files/" + i5,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -} -} -if(data31.skill_discovery !== undefined){ -if(typeof data31.skill_discovery !== "boolean"){ -const err89 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data31.standing_instructions !== undefined){ -if(typeof data31.standing_instructions !== "boolean"){ -const err90 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -} -if(data30.modules !== undefined){ -let data38 = data30.modules; -if((data38 !== null) && (!(Array.isArray(data38)))){ -const err91 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -if(Array.isArray(data38)){ -const len6 = data38.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data38[i6] !== "string"){ -const err92 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules/" + i6,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -} -if(data30.capabilities !== undefined){ -let data40 = data30.capabilities; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err93 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(Array.isArray(data40)){ -const len7 = data40.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data40[i7] !== "string"){ -const err94 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities/" + i7,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -} -} -if(data30.tools !== undefined){ -let data42 = data30.tools; -if((data42 !== null) && (!(Array.isArray(data42)))){ -const err95 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -if(Array.isArray(data42)){ -const len8 = data42.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data42[i8] !== "string"){ -const err96 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools/" + i8,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -} -} -if(data30.model !== undefined){ -let data44 = data30.model; -if(data44 && typeof data44 == "object" && !Array.isArray(data44)){ -if(data44.model === undefined){ -const err97 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -if(data44.provider === undefined){ -const err98 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -if(data44.effort === undefined){ -const err99 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -for(const key10 in data44){ -if(!(((key10 === "model") || (key10 === "provider")) || (key10 === "effort"))){ -const err100 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data44.model !== undefined){ -if(typeof data44.model !== "string"){ -const err101 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data44.provider !== undefined){ -if(typeof data44.provider !== "string"){ -const err102 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/provider",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data44.effort !== undefined){ -if(typeof data44.effort !== "string"){ -const err103 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/effort",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -} -else { -const err104 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data30.budgets !== undefined){ -let data48 = data30.budgets; -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -for(const key11 in data48){ -let data49 = data48[key11]; -if(!((typeof data49 == "number") && (!(data49 % 1) && !isNaN(data49)))){ -const err105 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets/" + key11.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -} -else { -const err106 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data30.report !== undefined){ -if(typeof data30.report !== "string"){ -const err107 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/report",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -} -else { -const err108 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -} -else { -const err109 = {instancePath:instancePath+"/definition/children",schemaPath:"#/properties/definition/properties/children/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data0.surface !== undefined){ -let data51 = data0.surface; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.auto_title === undefined){ -const err110 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "auto_title"},message:"must have required property '"+"auto_title"+"'"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -if(data51.goal_loop === undefined){ -const err111 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "goal_loop"},message:"must have required property '"+"goal_loop"+"'"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -for(const key12 in data51){ -if(!((key12 === "auto_title") || (key12 === "goal_loop"))){ -const err112 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data51.auto_title !== undefined){ -if(typeof data51.auto_title !== "boolean"){ -const err113 = {instancePath:instancePath+"/definition/surface/auto_title",schemaPath:"#/properties/definition/properties/surface/properties/auto_title/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data51.goal_loop !== undefined){ -if(typeof data51.goal_loop !== "boolean"){ -const err114 = {instancePath:instancePath+"/definition/surface/goal_loop",schemaPath:"#/properties/definition/properties/surface/properties/goal_loop/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -} -else { -const err115 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data0.hooks !== undefined){ -let data54 = data0.hooks; -if((data54 !== null) && (!(data54 && typeof data54 == "object" && !Array.isArray(data54)))){ -const err116 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.before_tool === undefined){ -const err117 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_tool"},message:"must have required property '"+"before_tool"+"'"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(data54.before_spawn === undefined){ -const err118 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_spawn"},message:"must have required property '"+"before_spawn"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data54.turn_start === undefined){ -const err119 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "turn_start"},message:"must have required property '"+"turn_start"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -for(const key13 in data54){ -if(!(((key13 === "before_tool") || (key13 === "before_spawn")) || (key13 === "turn_start"))){ -const err120 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -if(data54.before_tool !== undefined){ -let data55 = data54.before_tool; -if((data55 !== null) && (!(data55 && typeof data55 == "object" && !Array.isArray(data55)))){ -const err121 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_tool.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data55 && typeof data55 == "object" && !Array.isArray(data55)){ -if(data55.operations === undefined){ -const err122 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -if(data55.optional === undefined){ -const err123 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -if(data55.timeout_millis === undefined){ -const err124 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -for(const key14 in data55){ -if(!(((key14 === "operations") || (key14 === "optional")) || (key14 === "timeout_millis"))){ -const err125 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data55.operations !== undefined){ -let data56 = data55.operations; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err126 = {instancePath:instancePath+"/definition/hooks/before_tool/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_tool.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(Array.isArray(data56)){ -const len9 = data56.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data56[i9] !== "string"){ -const err127 = {instancePath:instancePath+"/definition/hooks/before_tool/operations/" + i9,schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -} -} -if(data55.optional !== undefined){ -if(typeof data55.optional !== "boolean"){ -const err128 = {instancePath:instancePath+"/definition/hooks/before_tool/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data55.timeout_millis !== undefined){ -let data59 = data55.timeout_millis; -if(!((typeof data59 == "number") && (!(data59 % 1) && !isNaN(data59)))){ -const err129 = {instancePath:instancePath+"/definition/hooks/before_tool/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -} -} -if(data54.before_spawn !== undefined){ -let data60 = data54.before_spawn; -if((data60 !== null) && (!(data60 && typeof data60 == "object" && !Array.isArray(data60)))){ -const err130 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -if(data60 && typeof data60 == "object" && !Array.isArray(data60)){ -if(data60.operations === undefined){ -const err131 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -if(data60.optional === undefined){ -const err132 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -if(data60.timeout_millis === undefined){ -const err133 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -for(const key15 in data60){ -if(!(((key15 === "operations") || (key15 === "optional")) || (key15 === "timeout_millis"))){ -const err134 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data60.operations !== undefined){ -let data61 = data60.operations; -if((data61 !== null) && (!(Array.isArray(data61)))){ -const err135 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_spawn.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -if(Array.isArray(data61)){ -const len10 = data61.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data61[i10] !== "string"){ -const err136 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations/" + i10,schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -} -} -if(data60.optional !== undefined){ -if(typeof data60.optional !== "boolean"){ -const err137 = {instancePath:instancePath+"/definition/hooks/before_spawn/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -if(data60.timeout_millis !== undefined){ -let data64 = data60.timeout_millis; -if(!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64)))){ -const err138 = {instancePath:instancePath+"/definition/hooks/before_spawn/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -if(data54.turn_start !== undefined){ -let data65 = data54.turn_start; -if((data65 !== null) && (!(data65 && typeof data65 == "object" && !Array.isArray(data65)))){ -const err139 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.turn_start.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.operations === undefined){ -const err140 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -if(data65.optional === undefined){ -const err141 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -if(data65.timeout_millis === undefined){ -const err142 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -for(const key16 in data65){ -if(!(((key16 === "operations") || (key16 === "optional")) || (key16 === "timeout_millis"))){ -const err143 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data65.operations !== undefined){ -let data66 = data65.operations; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err144 = {instancePath:instancePath+"/definition/hooks/turn_start/operations",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.turn_start.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(Array.isArray(data66)){ -const len11 = data66.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data66[i11] !== "string"){ -const err145 = {instancePath:instancePath+"/definition/hooks/turn_start/operations/" + i11,schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -} -} -if(data65.optional !== undefined){ -if(typeof data65.optional !== "boolean"){ -const err146 = {instancePath:instancePath+"/definition/hooks/turn_start/optional",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -if(data65.timeout_millis !== undefined){ -let data69 = data65.timeout_millis; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err147 = {instancePath:instancePath+"/definition/hooks/turn_start/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -} -} -} -} -} -else { -const err148 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err149 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -if(data.built_in !== undefined){ -if(typeof data.built_in !== "boolean"){ -const err150 = {instancePath:instancePath+"/built_in",schemaPath:"#/properties/built_in/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -if(data.registered_by !== undefined){ -if(typeof data.registered_by !== "string"){ -const err151 = {instancePath:instancePath+"/registered_by",schemaPath:"#/properties/registered_by/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err152 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -} -else { -const err153 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -validate60.errors = vErrors; -return errors === 0; -} - -export const DefinitionRegisterParams = validate61; -const schema62 = {"type":"object","properties":{"definition":{"type":"object","properties":{"id":{"type":"string"},"instructions":{"type":"object","properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":false},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":false},"compaction":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"threshold":{"type":"number"}},"required":["model","provider","threshold"],"additionalProperties":false},"mcp":{"type":"object","properties":{"servers":{"type":["null","array"],"items":{"type":"string"}}},"required":["servers"],"additionalProperties":false},"tools":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"input_schema":true,"output_schema":true,"timeout_millis":{"type":"integer"}},"required":["name","description","input_schema","output_schema","timeout_millis"],"additionalProperties":false}},"output":true,"children":{"type":"object","additionalProperties":{"type":"object","properties":{"instructions":{"type":["null","object"],"properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":false},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":false},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"output":true},"required":["instructions","modules","capabilities","tools","model","budgets","report","output"],"additionalProperties":false}},"surface":{"type":"object","properties":{"auto_title":{"type":"boolean"},"goal_loop":{"type":"boolean"}},"required":["auto_title","goal_loop"],"additionalProperties":false},"hooks":{"type":["null","object"],"properties":{"before_tool":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false},"before_spawn":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false},"turn_start":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":false}},"required":["before_tool","before_spawn","turn_start"],"additionalProperties":false}},"required":["id","instructions","modules","capabilities","model","compaction","mcp","tools","output","children","surface","hooks"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/DefinitionRegisterParams","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRegisterParams","required":["definition"],"additionalProperties":false}; - -function validate61(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRegisterParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "definition")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.definition !== undefined){ -let data0 = data.definition; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err2 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.instructions === undefined){ -const err3 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.modules === undefined){ -const err4 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.capabilities === undefined){ -const err5 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.model === undefined){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.compaction === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "compaction"},message:"must have required property '"+"compaction"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.mcp === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.tools === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.output === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.children === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "children"},message:"must have required property '"+"children"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.surface === undefined){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.hooks === undefined){ -const err13 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "hooks"},message:"must have required property '"+"hooks"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key1 in data0){ -if(!(func2.call(schema62.properties.definition.properties, key1))){ -const err14 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err15 = {instancePath:instancePath+"/definition/id",schemaPath:"#/properties/definition/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data0.instructions !== undefined){ -let data2 = data0.instructions; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.persona === undefined){ -const err16 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.rules === undefined){ -const err17 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data2.project_files === undefined){ -const err18 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2.skill_discovery === undefined){ -const err19 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2.standing_instructions === undefined){ -const err20 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key2 in data2){ -if(!(((((key2 === "persona") || (key2 === "rules")) || (key2 === "project_files")) || (key2 === "skill_discovery")) || (key2 === "standing_instructions"))){ -const err21 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.persona !== undefined){ -if(typeof data2.persona !== "string"){ -const err22 = {instancePath:instancePath+"/definition/instructions/persona",schemaPath:"#/properties/definition/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.rules !== undefined){ -if(typeof data2.rules !== "string"){ -const err23 = {instancePath:instancePath+"/definition/instructions/rules",schemaPath:"#/properties/definition/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.project_files !== undefined){ -let data5 = data2.project_files; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err24 = {instancePath:instancePath+"/definition/instructions/project_files",schemaPath:"#/properties/definition/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema62.properties.definition.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data5[i0] !== "string"){ -const err25 = {instancePath:instancePath+"/definition/instructions/project_files/" + i0,schemaPath:"#/properties/definition/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data2.skill_discovery !== undefined){ -if(typeof data2.skill_discovery !== "boolean"){ -const err26 = {instancePath:instancePath+"/definition/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.standing_instructions !== undefined){ -if(typeof data2.standing_instructions !== "boolean"){ -const err27 = {instancePath:instancePath+"/definition/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -else { -const err28 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data0.modules !== undefined){ -let data9 = data0.modules; -if((data9 !== null) && (!(Array.isArray(data9)))){ -const err29 = {instancePath:instancePath+"/definition/modules",schemaPath:"#/properties/definition/properties/modules/type",keyword:"type",params:{type: schema62.properties.definition.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(Array.isArray(data9)){ -const len1 = data9.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data9[i1] !== "string"){ -const err30 = {instancePath:instancePath+"/definition/modules/" + i1,schemaPath:"#/properties/definition/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -} -if(data0.capabilities !== undefined){ -let data11 = data0.capabilities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err31 = {instancePath:instancePath+"/definition/capabilities",schemaPath:"#/properties/definition/properties/capabilities/type",keyword:"type",params:{type: schema62.properties.definition.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err32 = {instancePath:instancePath+"/definition/capabilities/" + i2,schemaPath:"#/properties/definition/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -} -if(data0.model !== undefined){ -let data13 = data0.model; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.model === undefined){ -const err33 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data13.provider === undefined){ -const err34 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data13.effort === undefined){ -const err35 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -for(const key3 in data13){ -if(!(((key3 === "model") || (key3 === "provider")) || (key3 === "effort"))){ -const err36 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data13.model !== undefined){ -if(typeof data13.model !== "string"){ -const err37 = {instancePath:instancePath+"/definition/model/model",schemaPath:"#/properties/definition/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data13.provider !== undefined){ -if(typeof data13.provider !== "string"){ -const err38 = {instancePath:instancePath+"/definition/model/provider",schemaPath:"#/properties/definition/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data13.effort !== undefined){ -if(typeof data13.effort !== "string"){ -const err39 = {instancePath:instancePath+"/definition/model/effort",schemaPath:"#/properties/definition/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -} -else { -const err40 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data0.compaction !== undefined){ -let data17 = data0.compaction; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.model === undefined){ -const err41 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data17.provider === undefined){ -const err42 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data17.threshold === undefined){ -const err43 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "threshold"},message:"must have required property '"+"threshold"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -for(const key4 in data17){ -if(!(((key4 === "model") || (key4 === "provider")) || (key4 === "threshold"))){ -const err44 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.model !== undefined){ -if(typeof data17.model !== "string"){ -const err45 = {instancePath:instancePath+"/definition/compaction/model",schemaPath:"#/properties/definition/properties/compaction/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.provider !== undefined){ -if(typeof data17.provider !== "string"){ -const err46 = {instancePath:instancePath+"/definition/compaction/provider",schemaPath:"#/properties/definition/properties/compaction/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data17.threshold !== undefined){ -if(!(typeof data17.threshold == "number")){ -const err47 = {instancePath:instancePath+"/definition/compaction/threshold",schemaPath:"#/properties/definition/properties/compaction/properties/threshold/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -else { -const err48 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data0.mcp !== undefined){ -let data21 = data0.mcp; -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.servers === undefined){ -const err49 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -for(const key5 in data21){ -if(!(key5 === "servers")){ -const err50 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data21.servers !== undefined){ -let data22 = data21.servers; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err51 = {instancePath:instancePath+"/definition/mcp/servers",schemaPath:"#/properties/definition/properties/mcp/properties/servers/type",keyword:"type",params:{type: schema62.properties.definition.properties.mcp.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(Array.isArray(data22)){ -const len3 = data22.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data22[i3] !== "string"){ -const err52 = {instancePath:instancePath+"/definition/mcp/servers/" + i3,schemaPath:"#/properties/definition/properties/mcp/properties/servers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -} -} -} -else { -const err53 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data24 = data0.tools; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err54 = {instancePath:instancePath+"/definition/tools",schemaPath:"#/properties/definition/properties/tools/type",keyword:"type",params:{type: schema62.properties.definition.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(Array.isArray(data24)){ -const len4 = data24.length; -for(let i4=0; i4<len4; i4++){ -let data25 = data24[i4]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.name === undefined){ -const err55 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data25.description === undefined){ -const err56 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data25.input_schema === undefined){ -const err57 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "input_schema"},message:"must have required property '"+"input_schema"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data25.output_schema === undefined){ -const err58 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "output_schema"},message:"must have required property '"+"output_schema"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data25.timeout_millis === undefined){ -const err59 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -for(const key6 in data25){ -if(!(((((key6 === "name") || (key6 === "description")) || (key6 === "input_schema")) || (key6 === "output_schema")) || (key6 === "timeout_millis"))){ -const err60 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data25.name !== undefined){ -if(typeof data25.name !== "string"){ -const err61 = {instancePath:instancePath+"/definition/tools/" + i4+"/name",schemaPath:"#/properties/definition/properties/tools/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data25.description !== undefined){ -if(typeof data25.description !== "string"){ -const err62 = {instancePath:instancePath+"/definition/tools/" + i4+"/description",schemaPath:"#/properties/definition/properties/tools/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data25.timeout_millis !== undefined){ -let data28 = data25.timeout_millis; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err63 = {instancePath:instancePath+"/definition/tools/" + i4+"/timeout_millis",schemaPath:"#/properties/definition/properties/tools/items/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -} -else { -const err64 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data0.children !== undefined){ -let data29 = data0.children; -if(data29 && typeof data29 == "object" && !Array.isArray(data29)){ -for(const key7 in data29){ -let data30 = data29[key7]; -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.instructions === undefined){ -const err65 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data30.modules === undefined){ -const err66 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(data30.capabilities === undefined){ -const err67 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data30.tools === undefined){ -const err68 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data30.model === undefined){ -const err69 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data30.budgets === undefined){ -const err70 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data30.report === undefined){ -const err71 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data30.output === undefined){ -const err72 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -for(const key8 in data30){ -if(!((((((((key8 === "instructions") || (key8 === "modules")) || (key8 === "capabilities")) || (key8 === "tools")) || (key8 === "model")) || (key8 === "budgets")) || (key8 === "report")) || (key8 === "output"))){ -const err73 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data30.instructions !== undefined){ -let data31 = data30.instructions; -if((data31 !== null) && (!(data31 && typeof data31 == "object" && !Array.isArray(data31)))){ -const err74 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.instructions.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -if(data31.persona === undefined){ -const err75 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(data31.rules === undefined){ -const err76 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -if(data31.project_files === undefined){ -const err77 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data31.skill_discovery === undefined){ -const err78 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data31.standing_instructions === undefined){ -const err79 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -for(const key9 in data31){ -if(!(((((key9 === "persona") || (key9 === "rules")) || (key9 === "project_files")) || (key9 === "skill_discovery")) || (key9 === "standing_instructions"))){ -const err80 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data31.persona !== undefined){ -if(typeof data31.persona !== "string"){ -const err81 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/persona",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data31.rules !== undefined){ -if(typeof data31.rules !== "string"){ -const err82 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/rules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -if(data31.project_files !== undefined){ -let data34 = data31.project_files; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err83 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(Array.isArray(data34)){ -const len5 = data34.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data34[i5] !== "string"){ -const err84 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files/" + i5,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -} -} -if(data31.skill_discovery !== undefined){ -if(typeof data31.skill_discovery !== "boolean"){ -const err85 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data31.standing_instructions !== undefined){ -if(typeof data31.standing_instructions !== "boolean"){ -const err86 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -} -} -if(data30.modules !== undefined){ -let data38 = data30.modules; -if((data38 !== null) && (!(Array.isArray(data38)))){ -const err87 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(Array.isArray(data38)){ -const len6 = data38.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data38[i6] !== "string"){ -const err88 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules/" + i6,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -} -} -if(data30.capabilities !== undefined){ -let data40 = data30.capabilities; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err89 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(Array.isArray(data40)){ -const len7 = data40.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data40[i7] !== "string"){ -const err90 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities/" + i7,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -} -if(data30.tools !== undefined){ -let data42 = data30.tools; -if((data42 !== null) && (!(Array.isArray(data42)))){ -const err91 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -if(Array.isArray(data42)){ -const len8 = data42.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data42[i8] !== "string"){ -const err92 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools/" + i8,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -} -if(data30.model !== undefined){ -let data44 = data30.model; -if(data44 && typeof data44 == "object" && !Array.isArray(data44)){ -if(data44.model === undefined){ -const err93 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(data44.provider === undefined){ -const err94 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(data44.effort === undefined){ -const err95 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -for(const key10 in data44){ -if(!(((key10 === "model") || (key10 === "provider")) || (key10 === "effort"))){ -const err96 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data44.model !== undefined){ -if(typeof data44.model !== "string"){ -const err97 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data44.provider !== undefined){ -if(typeof data44.provider !== "string"){ -const err98 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/provider",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data44.effort !== undefined){ -if(typeof data44.effort !== "string"){ -const err99 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/effort",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -} -else { -const err100 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data30.budgets !== undefined){ -let data48 = data30.budgets; -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -for(const key11 in data48){ -let data49 = data48[key11]; -if(!((typeof data49 == "number") && (!(data49 % 1) && !isNaN(data49)))){ -const err101 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets/" + key11.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -} -else { -const err102 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data30.report !== undefined){ -if(typeof data30.report !== "string"){ -const err103 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1")+"/report",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -} -else { -const err104 = {instancePath:instancePath+"/definition/children/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -} -else { -const err105 = {instancePath:instancePath+"/definition/children",schemaPath:"#/properties/definition/properties/children/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data0.surface !== undefined){ -let data51 = data0.surface; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.auto_title === undefined){ -const err106 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "auto_title"},message:"must have required property '"+"auto_title"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(data51.goal_loop === undefined){ -const err107 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "goal_loop"},message:"must have required property '"+"goal_loop"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -for(const key12 in data51){ -if(!((key12 === "auto_title") || (key12 === "goal_loop"))){ -const err108 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data51.auto_title !== undefined){ -if(typeof data51.auto_title !== "boolean"){ -const err109 = {instancePath:instancePath+"/definition/surface/auto_title",schemaPath:"#/properties/definition/properties/surface/properties/auto_title/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data51.goal_loop !== undefined){ -if(typeof data51.goal_loop !== "boolean"){ -const err110 = {instancePath:instancePath+"/definition/surface/goal_loop",schemaPath:"#/properties/definition/properties/surface/properties/goal_loop/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -} -else { -const err111 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data0.hooks !== undefined){ -let data54 = data0.hooks; -if((data54 !== null) && (!(data54 && typeof data54 == "object" && !Array.isArray(data54)))){ -const err112 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.before_tool === undefined){ -const err113 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_tool"},message:"must have required property '"+"before_tool"+"'"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(data54.before_spawn === undefined){ -const err114 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_spawn"},message:"must have required property '"+"before_spawn"+"'"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data54.turn_start === undefined){ -const err115 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "turn_start"},message:"must have required property '"+"turn_start"+"'"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -for(const key13 in data54){ -if(!(((key13 === "before_tool") || (key13 === "before_spawn")) || (key13 === "turn_start"))){ -const err116 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data54.before_tool !== undefined){ -let data55 = data54.before_tool; -if((data55 !== null) && (!(data55 && typeof data55 == "object" && !Array.isArray(data55)))){ -const err117 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_tool.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(data55 && typeof data55 == "object" && !Array.isArray(data55)){ -if(data55.operations === undefined){ -const err118 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data55.optional === undefined){ -const err119 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data55.timeout_millis === undefined){ -const err120 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -for(const key14 in data55){ -if(!(((key14 === "operations") || (key14 === "optional")) || (key14 === "timeout_millis"))){ -const err121 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -if(data55.operations !== undefined){ -let data56 = data55.operations; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err122 = {instancePath:instancePath+"/definition/hooks/before_tool/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_tool.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -if(Array.isArray(data56)){ -const len9 = data56.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data56[i9] !== "string"){ -const err123 = {instancePath:instancePath+"/definition/hooks/before_tool/operations/" + i9,schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -} -} -if(data55.optional !== undefined){ -if(typeof data55.optional !== "boolean"){ -const err124 = {instancePath:instancePath+"/definition/hooks/before_tool/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data55.timeout_millis !== undefined){ -let data59 = data55.timeout_millis; -if(!((typeof data59 == "number") && (!(data59 % 1) && !isNaN(data59)))){ -const err125 = {instancePath:instancePath+"/definition/hooks/before_tool/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -} -} -if(data54.before_spawn !== undefined){ -let data60 = data54.before_spawn; -if((data60 !== null) && (!(data60 && typeof data60 == "object" && !Array.isArray(data60)))){ -const err126 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(data60 && typeof data60 == "object" && !Array.isArray(data60)){ -if(data60.operations === undefined){ -const err127 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -if(data60.optional === undefined){ -const err128 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -if(data60.timeout_millis === undefined){ -const err129 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -for(const key15 in data60){ -if(!(((key15 === "operations") || (key15 === "optional")) || (key15 === "timeout_millis"))){ -const err130 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -if(data60.operations !== undefined){ -let data61 = data60.operations; -if((data61 !== null) && (!(Array.isArray(data61)))){ -const err131 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_spawn.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -if(Array.isArray(data61)){ -const len10 = data61.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data61[i10] !== "string"){ -const err132 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations/" + i10,schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -} -} -if(data60.optional !== undefined){ -if(typeof data60.optional !== "boolean"){ -const err133 = {instancePath:instancePath+"/definition/hooks/before_spawn/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data60.timeout_millis !== undefined){ -let data64 = data60.timeout_millis; -if(!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64)))){ -const err134 = {instancePath:instancePath+"/definition/hooks/before_spawn/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -} -} -if(data54.turn_start !== undefined){ -let data65 = data54.turn_start; -if((data65 !== null) && (!(data65 && typeof data65 == "object" && !Array.isArray(data65)))){ -const err135 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.turn_start.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.operations === undefined){ -const err136 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -if(data65.optional === undefined){ -const err137 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -if(data65.timeout_millis === undefined){ -const err138 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -for(const key16 in data65){ -if(!(((key16 === "operations") || (key16 === "optional")) || (key16 === "timeout_millis"))){ -const err139 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -if(data65.operations !== undefined){ -let data66 = data65.operations; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err140 = {instancePath:instancePath+"/definition/hooks/turn_start/operations",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.turn_start.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -if(Array.isArray(data66)){ -const len11 = data66.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data66[i11] !== "string"){ -const err141 = {instancePath:instancePath+"/definition/hooks/turn_start/operations/" + i11,schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -} -} -if(data65.optional !== undefined){ -if(typeof data65.optional !== "boolean"){ -const err142 = {instancePath:instancePath+"/definition/hooks/turn_start/optional",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data65.timeout_millis !== undefined){ -let data69 = data65.timeout_millis; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err143 = {instancePath:instancePath+"/definition/hooks/turn_start/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -} -} -} -} -} -else { -const err144 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -} -else { -const err145 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -validate61.errors = vErrors; -return errors === 0; -} - -export const DefinitionRegisterResult = validate62; -const schema63 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"},"created":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/DefinitionRegisterResult","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRegisterResult","required":["id","revision","created"],"additionalProperties":false}; - -function validate62(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRegisterResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.created === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created"},message:"must have required property '"+"created"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "revision")) || (key0 === "created"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.created !== undefined){ -if(typeof data.created !== "boolean"){ -const err6 = {instancePath:instancePath+"/created",schemaPath:"#/properties/created/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate62.errors = vErrors; -return errors === 0; -} - -export const EffortParams = validate63; -const schema64 = {"type":"object","properties":{"effort":{"type":"string"},"persist_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/EffortParams","$schema":"http://json-schema.org/draft-07/schema#","title":"EffortParams","required":["effort","persist_default"],"additionalProperties":false}; - -function validate63(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EffortParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.effort === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.persist_default === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "persist_default"},message:"must have required property '"+"persist_default"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "effort") || (key0 === "persist_default"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err3 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.persist_default !== undefined){ -if(typeof data.persist_default !== "boolean"){ -const err4 = {instancePath:instancePath+"/persist_default",schemaPath:"#/properties/persist_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate63.errors = vErrors; -return errors === 0; -} - -export const EffortResult = validate64; -const schema65 = {"type":"object","properties":{"effort":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/EffortResult","$schema":"http://json-schema.org/draft-07/schema#","title":"EffortResult","required":["effort"],"additionalProperties":false}; - -function validate64(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EffortResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.effort === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "effort")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err2 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate64.errors = vErrors; -return errors === 0; -} - -export const Empty = validate65; -const schema66 = {"type":"object","$id":"https://whip.dev/protocol/v6/Empty","$schema":"http://json-schema.org/draft-07/schema#","title":"Empty","additionalProperties":false}; - -function validate65(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Empty" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate65.errors = vErrors; -return errors === 0; -} - -export const EmptyParams = validate66; -const schema67 = {"type":"object","$id":"https://whip.dev/protocol/v6/EmptyParams","$schema":"http://json-schema.org/draft-07/schema#","title":"EmptyParams","additionalProperties":false}; - -function validate66(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EmptyParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate66.errors = vErrors; -return errors === 0; -} - -export const EventNotification = validate67; -const schema68 = {"type":"object","properties":{"event":{"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["root_id","seq","kind"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/EventNotification","$schema":"http://json-schema.org/draft-07/schema#","title":"EventNotification","required":["event"],"additionalProperties":false}; - -function validate67(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EventNotification" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.event === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "event"},message:"must have required property '"+"event"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "event")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.event !== undefined){ -let data0 = data.event; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.root_id === undefined){ -const err2 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.seq === undefined){ -const err3 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.kind === undefined){ -const err4 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key1 in data0){ -if(!(((((key1 === "subscription_id") || (key1 === "root_id")) || (key1 === "seq")) || (key1 === "kind")) || (key1 === "payload"))){ -const err5 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.subscription_id !== undefined){ -if(typeof data0.subscription_id !== "string"){ -const err6 = {instancePath:instancePath+"/event/subscription_id",schemaPath:"#/properties/event/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/event/root_id",schemaPath:"#/properties/event/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.seq !== undefined){ -let data3 = data0.seq; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err8 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err9 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err11 = {instancePath:instancePath+"/event/kind",schemaPath:"#/properties/event/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate67.errors = vErrors; -return errors === 0; -} - -export const ExecutorBindParams = validate68; -const schema69 = {"type":"object","properties":{"definition":{"type":"string"},"revision":{"type":"string"},"tools":{"type":["null","array"],"items":{"type":"string"}},"hooks":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ExecutorBindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorBindParams","required":["definition","revision","tools"],"additionalProperties":false}; - -function validate68(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorBindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.tools === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "definition") || (key0 === "revision")) || (key0 === "tools")) || (key0 === "hooks"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err4 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.tools !== undefined){ -let data2 = data.tools; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err6 = {instancePath:instancePath+"/tools",schemaPath:"#/properties/tools/type",keyword:"type",params:{type: schema69.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err7 = {instancePath:instancePath+"/tools/" + i0,schemaPath:"#/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data4 = data.hooks; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err8 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema69.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data4[i1] !== "string"){ -const err9 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate68.errors = vErrors; -return errors === 0; -} - -export const ExecutorBindResult = validate69; -const schema70 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"tools":{"type":["null","array"],"items":{"type":"string"}},"hooks":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ExecutorBindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorBindResult","required":["generation","tools"],"additionalProperties":false}; - -function validate69(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorBindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.tools === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "generation") || (key0 === "tools")) || (key0 === "hooks"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.tools !== undefined){ -let data1 = data.tools; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err6 = {instancePath:instancePath+"/tools",schemaPath:"#/properties/tools/type",keyword:"type",params:{type: schema70.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err7 = {instancePath:instancePath+"/tools/" + i0,schemaPath:"#/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data3 = data.hooks; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema70.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data3)){ -const len1 = data3.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data3[i1] !== "string"){ -const err9 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate69.errors = vErrors; -return errors === 0; -} - -export const ExecutorPendingParams = validate70; -const schema71 = {"type":"object","properties":{"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ExecutorPendingParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorPendingParams","required":["definition","revision","generation"],"additionalProperties":false}; - -function validate70(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorPendingParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.generation === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "definition") || (key0 === "revision")) || (key0 === "generation"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err4 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.generation !== undefined){ -let data2 = data.generation; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err7 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate70.errors = vErrors; -return errors === 0; -} - -export const ExecutorPendingResult = validate71; -const schema72 = {"type":"object","properties":{"invocations":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":false}},"hooks":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"hook":{"type":"string"},"operation":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"request":{"type":"object","properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":false},"resolved":{"type":"object","properties":{"browser_attachments":{"type":["null","array"],"items":{"type":"string"}},"definition":{"type":"string"},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"}},"required":["definition","modules","capabilities","tools","budgets","report"],"additionalProperties":false}},"required":["request","resolved"],"additionalProperties":false},"input":{"type":"string"},"permission_mode":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","hook","permission_mode","deadline_millis"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/ExecutorPendingResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorPendingResult","required":["invocations"],"additionalProperties":false}; - -function validate71(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorPendingResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocations === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocations"},message:"must have required property '"+"invocations"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "invocations") || (key0 === "hooks"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.invocations !== undefined){ -let data0 = data.invocations; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/invocations",schemaPath:"#/properties/invocations/type",keyword:"type",params:{type: schema72.properties.invocations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.invocation_id === undefined){ -const err3 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.definition === undefined){ -const err4 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.revision === undefined){ -const err5 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.generation === undefined){ -const err6 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.root_id === undefined){ -const err7 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.agent_id === undefined){ -const err8 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.turn_id === undefined){ -const err9 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.tool === undefined){ -const err10 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data1.input === undefined){ -const err11 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "input"},message:"must have required property '"+"input"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data1.deadline_millis === undefined){ -const err12 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -for(const key1 in data1){ -if(!(func2.call(schema72.properties.invocations.items.properties, key1))){ -const err13 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.invocation_id !== undefined){ -if(typeof data1.invocation_id !== "string"){ -const err14 = {instancePath:instancePath+"/invocations/" + i0+"/invocation_id",schemaPath:"#/properties/invocations/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.definition !== undefined){ -if(typeof data1.definition !== "string"){ -const err15 = {instancePath:instancePath+"/invocations/" + i0+"/definition",schemaPath:"#/properties/invocations/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data1.revision !== undefined){ -if(typeof data1.revision !== "string"){ -const err16 = {instancePath:instancePath+"/invocations/" + i0+"/revision",schemaPath:"#/properties/invocations/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data1.generation !== undefined){ -let data5 = data1.generation; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err17 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err18 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -else { -const err19 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err20 = {instancePath:instancePath+"/invocations/" + i0+"/root_id",schemaPath:"#/properties/invocations/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data1.agent_id !== undefined){ -if(typeof data1.agent_id !== "string"){ -const err21 = {instancePath:instancePath+"/invocations/" + i0+"/agent_id",schemaPath:"#/properties/invocations/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data1.turn_id !== undefined){ -if(typeof data1.turn_id !== "string"){ -const err22 = {instancePath:instancePath+"/invocations/" + i0+"/turn_id",schemaPath:"#/properties/invocations/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data1.tool !== undefined){ -if(typeof data1.tool !== "string"){ -const err23 = {instancePath:instancePath+"/invocations/" + i0+"/tool",schemaPath:"#/properties/invocations/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data1.deadline_millis !== undefined){ -let data10 = data1.deadline_millis; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err24 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err25 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -else { -const err27 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data11 = data.hooks; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err28 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema72.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(Array.isArray(data11)){ -const len1 = data11.length; -for(let i1=0; i1<len1; i1++){ -let data12 = data11[i1]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.invocation_id === undefined){ -const err29 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data12.definition === undefined){ -const err30 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data12.revision === undefined){ -const err31 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data12.generation === undefined){ -const err32 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data12.root_id === undefined){ -const err33 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data12.agent_id === undefined){ -const err34 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data12.turn_id === undefined){ -const err35 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data12.hook === undefined){ -const err36 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "hook"},message:"must have required property '"+"hook"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data12.permission_mode === undefined){ -const err37 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "permission_mode"},message:"must have required property '"+"permission_mode"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data12.deadline_millis === undefined){ -const err38 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -for(const key2 in data12){ -if(!(func2.call(schema72.properties.hooks.items.properties, key2))){ -const err39 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data12.invocation_id !== undefined){ -if(typeof data12.invocation_id !== "string"){ -const err40 = {instancePath:instancePath+"/hooks/" + i1+"/invocation_id",schemaPath:"#/properties/hooks/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data12.definition !== undefined){ -if(typeof data12.definition !== "string"){ -const err41 = {instancePath:instancePath+"/hooks/" + i1+"/definition",schemaPath:"#/properties/hooks/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data12.revision !== undefined){ -if(typeof data12.revision !== "string"){ -const err42 = {instancePath:instancePath+"/hooks/" + i1+"/revision",schemaPath:"#/properties/hooks/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data12.generation !== undefined){ -let data16 = data12.generation; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err43 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err44 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data12.root_id !== undefined){ -if(typeof data12.root_id !== "string"){ -const err46 = {instancePath:instancePath+"/hooks/" + i1+"/root_id",schemaPath:"#/properties/hooks/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data12.agent_id !== undefined){ -if(typeof data12.agent_id !== "string"){ -const err47 = {instancePath:instancePath+"/hooks/" + i1+"/agent_id",schemaPath:"#/properties/hooks/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data12.turn_id !== undefined){ -if(typeof data12.turn_id !== "string"){ -const err48 = {instancePath:instancePath+"/hooks/" + i1+"/turn_id",schemaPath:"#/properties/hooks/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data12.hook !== undefined){ -if(typeof data12.hook !== "string"){ -const err49 = {instancePath:instancePath+"/hooks/" + i1+"/hook",schemaPath:"#/properties/hooks/items/properties/hook/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data12.operation !== undefined){ -if(typeof data12.operation !== "string"){ -const err50 = {instancePath:instancePath+"/hooks/" + i1+"/operation",schemaPath:"#/properties/hooks/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data12.spawn !== undefined){ -let data22 = data12.spawn; -if((data22 !== null) && (!(data22 && typeof data22 == "object" && !Array.isArray(data22)))){ -const err51 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.request === undefined){ -const err52 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/required",keyword:"required",params:{missingProperty: "request"},message:"must have required property '"+"request"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data22.resolved === undefined){ -const err53 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/required",keyword:"required",params:{missingProperty: "resolved"},message:"must have required property '"+"resolved"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -for(const key3 in data22){ -if(!((key3 === "request") || (key3 === "resolved"))){ -const err54 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data22.request !== undefined){ -let data23 = data22.request; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt === undefined){ -const err55 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data23.name === undefined){ -const err56 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data23.definition === undefined){ -const err57 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data23.capabilities === undefined){ -const err58 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data23.tools === undefined){ -const err59 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data23.budgets === undefined){ -const err60 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data23.report === undefined){ -const err61 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data23.model === undefined){ -const err62 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data23.provider === undefined){ -const err63 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data23.effort === undefined){ -const err64 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -for(const key4 in data23){ -if(!(func2.call(schema72.properties.hooks.items.properties.spawn.properties.request.properties, key4))){ -const err65 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data23.prompt !== undefined){ -if(typeof data23.prompt !== "string"){ -const err66 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/prompt",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data23.name !== undefined){ -if(typeof data23.name !== "string"){ -const err67 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/name",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data23.definition !== undefined){ -if(typeof data23.definition !== "string"){ -const err68 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/definition",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data23.capabilities !== undefined){ -let data27 = data23.capabilities; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err69 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/capabilities",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/capabilities/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err70 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/capabilities/" + i2,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -} -} -if(data23.tools !== undefined){ -let data29 = data23.tools; -if((data29 !== null) && (!(Array.isArray(data29)))){ -const err71 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/tools",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/tools/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(Array.isArray(data29)){ -const len3 = data29.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data29[i3] !== "string"){ -const err72 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/tools/" + i3,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -} -if(data23.budgets !== undefined){ -let data31 = data23.budgets; -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -for(const key5 in data31){ -let data32 = data31[key5]; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err73 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/budgets/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -} -else { -const err74 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/budgets",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data23.report !== undefined){ -if(typeof data23.report !== "string"){ -const err75 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/report",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data23.model !== undefined){ -if(typeof data23.model !== "string"){ -const err76 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/model",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data23.provider !== undefined){ -if(typeof data23.provider !== "string"){ -const err77 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/provider",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data23.effort !== undefined){ -if(typeof data23.effort !== "string"){ -const err78 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/effort",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data23.browser_attachments !== undefined){ -let data37 = data23.browser_attachments; -if((data37 !== null) && (!(Array.isArray(data37)))){ -const err79 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/browser_attachments",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/browser_attachments/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(Array.isArray(data37)){ -const len4 = data37.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data37[i4] !== "string"){ -const err80 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/browser_attachments/" + i4,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -} -} -} -else { -const err81 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data22.resolved !== undefined){ -let data39 = data22.resolved; -if(data39 && typeof data39 == "object" && !Array.isArray(data39)){ -if(data39.definition === undefined){ -const err82 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data39.modules === undefined){ -const err83 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data39.capabilities === undefined){ -const err84 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data39.tools === undefined){ -const err85 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data39.budgets === undefined){ -const err86 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data39.report === undefined){ -const err87 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -for(const key6 in data39){ -if(!(((((((key6 === "browser_attachments") || (key6 === "definition")) || (key6 === "modules")) || (key6 === "capabilities")) || (key6 === "tools")) || (key6 === "budgets")) || (key6 === "report"))){ -const err88 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data39.browser_attachments !== undefined){ -let data40 = data39.browser_attachments; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err89 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/browser_attachments",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/browser_attachments/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(Array.isArray(data40)){ -const len5 = data40.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data40[i5] !== "string"){ -const err90 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/browser_attachments/" + i5,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -} -if(data39.definition !== undefined){ -if(typeof data39.definition !== "string"){ -const err91 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/definition",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data39.modules !== undefined){ -let data43 = data39.modules; -if((data43 !== null) && (!(Array.isArray(data43)))){ -const err92 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/modules",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/modules/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -if(Array.isArray(data43)){ -const len6 = data43.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data43[i6] !== "string"){ -const err93 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/modules/" + i6,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -} -} -if(data39.capabilities !== undefined){ -let data45 = data39.capabilities; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err94 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/capabilities",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/capabilities/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(Array.isArray(data45)){ -const len7 = data45.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data45[i7] !== "string"){ -const err95 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/capabilities/" + i7,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -} -} -if(data39.tools !== undefined){ -let data47 = data39.tools; -if((data47 !== null) && (!(Array.isArray(data47)))){ -const err96 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/tools",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/tools/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -if(Array.isArray(data47)){ -const len8 = data47.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data47[i8] !== "string"){ -const err97 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/tools/" + i8,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -} -if(data39.budgets !== undefined){ -let data49 = data39.budgets; -if(data49 && typeof data49 == "object" && !Array.isArray(data49)){ -for(const key7 in data49){ -let data50 = data49[key7]; -if(!((typeof data50 == "number") && (!(data50 % 1) && !isNaN(data50)))){ -const err98 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/budgets/" + key7.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -else { -const err99 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/budgets",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data39.report !== undefined){ -if(typeof data39.report !== "string"){ -const err100 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/report",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -} -else { -const err101 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -} -} -if(data12.input !== undefined){ -if(typeof data12.input !== "string"){ -const err102 = {instancePath:instancePath+"/hooks/" + i1+"/input",schemaPath:"#/properties/hooks/items/properties/input/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data12.permission_mode !== undefined){ -if(typeof data12.permission_mode !== "string"){ -const err103 = {instancePath:instancePath+"/hooks/" + i1+"/permission_mode",schemaPath:"#/properties/hooks/items/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data12.deadline_millis !== undefined){ -let data54 = data12.deadline_millis; -if(typeof data54 === "string"){ -if(!pattern0.test(data54)){ -const err104 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -if(!(formats0.validate(data54))){ -const err105 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -else { -const err106 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -} -else { -const err107 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -} -} -} -else { -const err108 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -validate71.errors = vErrors; -return errors === 0; -} - -export const ForkParams = validate72; -const schema73 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"title":{"type":"string"},"cut":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ForkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ForkParams","required":["expected_revision"],"additionalProperties":false}; - -function validate72(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ForkParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.expected_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_revision"},message:"must have required property '"+"expected_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "expected_revision") || (key0 === "title")) || (key0 === "cut"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err2 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema73.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err5 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cut !== undefined){ -let data2 = data.cut; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err6 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate72.errors = vErrors; -return errors === 0; -} - -export const GatewayStatus = validate73; -const schema74 = {"type":"object","properties":{"state":{"type":"string"},"endpoint":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/GatewayStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"GatewayStatus","required":["state"],"additionalProperties":false}; - -function validate73(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GatewayStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.state === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "state") || (key0 === "endpoint")) || (key0 === "error"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.state !== undefined){ -if(typeof data.state !== "string"){ -const err2 = {instancePath:instancePath+"/state",schemaPath:"#/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.endpoint !== undefined){ -if(typeof data.endpoint !== "string"){ -const err3 = {instancePath:instancePath+"/endpoint",schemaPath:"#/properties/endpoint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err4 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate73.errors = vErrors; -return errors === 0; -} - -export const GoalContextParams = validate74; -const schema75 = {"type":"object","properties":{"window":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/GoalContextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"GoalContextParams","additionalProperties":false}; - -function validate74(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GoalContextParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "window")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.window !== undefined){ -let data0 = data.window; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err1 = {instancePath:instancePath+"/window",schemaPath:"#/properties/window/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate74.errors = vErrors; -return errors === 0; -} - -export const GoalResult = validate75; -const schema76 = {"type":"object","properties":{"goal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/GoalResult","$schema":"http://json-schema.org/draft-07/schema#","title":"GoalResult","required":["goal"],"additionalProperties":false}; - -function validate75(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GoalResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.goal === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "goal")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.goal !== undefined){ -if(typeof data.goal !== "string"){ -const err2 = {instancePath:instancePath+"/goal",schemaPath:"#/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate75.errors = vErrors; -return errors === 0; -} - -export const HistoryPageParams = validate76; -const schema77 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"after_seq":{"type":"integer"},"before_seq":{"type":"integer"},"through_seq":{"type":"integer"},"revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"max_bytes":{"type":"integer"},"recent":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HistoryPageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HistoryPageParams","required":["root_id","agent_id","through_seq","limit","max_bytes"],"additionalProperties":false}; - -function validate76(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HistoryPageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.through_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.max_bytes === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema77.properties, key0))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err7 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.after_seq !== undefined){ -let data2 = data.after_seq; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err8 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.before_seq !== undefined){ -let data3 = data.before_seq; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err9 = {instancePath:instancePath+"/before_seq",schemaPath:"#/properties/before_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.through_seq !== undefined){ -let data4 = data.through_seq; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err10 = {instancePath:instancePath+"/through_seq",schemaPath:"#/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.revision !== undefined){ -let data5 = data.revision; -if((typeof data5 !== "string") && (data5 !== null)){ -const err11 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: schema77.properties.revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err12 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err13 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -if(data.limit !== undefined){ -let data6 = data.limit; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err14 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data7 = data.max_bytes; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err15 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.recent !== undefined){ -if(typeof data.recent !== "boolean"){ -const err16 = {instancePath:instancePath+"/recent",schemaPath:"#/properties/recent/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate76.errors = vErrors; -return errors === 0; -} - -export const HookInvokeParams = validate77; -const schema78 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"hook":{"type":"string"},"operation":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"request":{"type":"object","properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":false},"resolved":{"type":"object","properties":{"browser_attachments":{"type":["null","array"],"items":{"type":"string"}},"definition":{"type":"string"},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"}},"required":["definition","modules","capabilities","tools","budgets","report"],"additionalProperties":false}},"required":["request","resolved"],"additionalProperties":false},"input":{"type":"string"},"permission_mode":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/HookInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HookInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","hook","permission_mode","deadline_millis"],"additionalProperties":false}; - -function validate77(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HookInvokeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.definition === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.agent_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.turn_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.hook === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "hook"},message:"must have required property '"+"hook"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.permission_mode === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permission_mode"},message:"must have required property '"+"permission_mode"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema78.properties, key0))){ -const err10 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err11 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err13 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.generation !== undefined){ -let data3 = data.generation; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err14 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err15 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -else { -const err16 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err17 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err18 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err19 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.hook !== undefined){ -if(typeof data.hook !== "string"){ -const err20 = {instancePath:instancePath+"/hook",schemaPath:"#/properties/hook/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err21 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.spawn !== undefined){ -let data9 = data.spawn; -if((data9 !== null) && (!(data9 && typeof data9 == "object" && !Array.isArray(data9)))){ -const err22 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/type",keyword:"type",params:{type: schema78.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.request === undefined){ -const err23 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "request"},message:"must have required property '"+"request"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data9.resolved === undefined){ -const err24 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "resolved"},message:"must have required property '"+"resolved"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -for(const key1 in data9){ -if(!((key1 === "request") || (key1 === "resolved"))){ -const err25 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data9.request !== undefined){ -let data10 = data9.request; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.prompt === undefined){ -const err26 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data10.name === undefined){ -const err27 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data10.definition === undefined){ -const err28 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data10.capabilities === undefined){ -const err29 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data10.tools === undefined){ -const err30 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data10.budgets === undefined){ -const err31 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data10.report === undefined){ -const err32 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data10.model === undefined){ -const err33 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data10.provider === undefined){ -const err34 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data10.effort === undefined){ -const err35 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -for(const key2 in data10){ -if(!(func2.call(schema78.properties.spawn.properties.request.properties, key2))){ -const err36 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data10.prompt !== undefined){ -if(typeof data10.prompt !== "string"){ -const err37 = {instancePath:instancePath+"/spawn/request/prompt",schemaPath:"#/properties/spawn/properties/request/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data10.name !== undefined){ -if(typeof data10.name !== "string"){ -const err38 = {instancePath:instancePath+"/spawn/request/name",schemaPath:"#/properties/spawn/properties/request/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data10.definition !== undefined){ -if(typeof data10.definition !== "string"){ -const err39 = {instancePath:instancePath+"/spawn/request/definition",schemaPath:"#/properties/spawn/properties/request/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data10.capabilities !== undefined){ -let data14 = data10.capabilities; -if((data14 !== null) && (!(Array.isArray(data14)))){ -const err40 = {instancePath:instancePath+"/spawn/request/capabilities",schemaPath:"#/properties/spawn/properties/request/properties/capabilities/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(Array.isArray(data14)){ -const len0 = data14.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data14[i0] !== "string"){ -const err41 = {instancePath:instancePath+"/spawn/request/capabilities/" + i0,schemaPath:"#/properties/spawn/properties/request/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -} -if(data10.tools !== undefined){ -let data16 = data10.tools; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err42 = {instancePath:instancePath+"/spawn/request/tools",schemaPath:"#/properties/spawn/properties/request/properties/tools/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(Array.isArray(data16)){ -const len1 = data16.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data16[i1] !== "string"){ -const err43 = {instancePath:instancePath+"/spawn/request/tools/" + i1,schemaPath:"#/properties/spawn/properties/request/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -} -if(data10.budgets !== undefined){ -let data18 = data10.budgets; -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -for(const key3 in data18){ -let data19 = data18[key3]; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err44 = {instancePath:instancePath+"/spawn/request/budgets/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/request/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -else { -const err45 = {instancePath:instancePath+"/spawn/request/budgets",schemaPath:"#/properties/spawn/properties/request/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data10.report !== undefined){ -if(typeof data10.report !== "string"){ -const err46 = {instancePath:instancePath+"/spawn/request/report",schemaPath:"#/properties/spawn/properties/request/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data10.model !== undefined){ -if(typeof data10.model !== "string"){ -const err47 = {instancePath:instancePath+"/spawn/request/model",schemaPath:"#/properties/spawn/properties/request/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data10.provider !== undefined){ -if(typeof data10.provider !== "string"){ -const err48 = {instancePath:instancePath+"/spawn/request/provider",schemaPath:"#/properties/spawn/properties/request/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data10.effort !== undefined){ -if(typeof data10.effort !== "string"){ -const err49 = {instancePath:instancePath+"/spawn/request/effort",schemaPath:"#/properties/spawn/properties/request/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data10.browser_attachments !== undefined){ -let data24 = data10.browser_attachments; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err50 = {instancePath:instancePath+"/spawn/request/browser_attachments",schemaPath:"#/properties/spawn/properties/request/properties/browser_attachments/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(Array.isArray(data24)){ -const len2 = data24.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data24[i2] !== "string"){ -const err51 = {instancePath:instancePath+"/spawn/request/browser_attachments/" + i2,schemaPath:"#/properties/spawn/properties/request/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -} -} -else { -const err52 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data9.resolved !== undefined){ -let data26 = data9.resolved; -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.definition === undefined){ -const err53 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data26.modules === undefined){ -const err54 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data26.capabilities === undefined){ -const err55 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data26.tools === undefined){ -const err56 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data26.budgets === undefined){ -const err57 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data26.report === undefined){ -const err58 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -for(const key4 in data26){ -if(!(((((((key4 === "browser_attachments") || (key4 === "definition")) || (key4 === "modules")) || (key4 === "capabilities")) || (key4 === "tools")) || (key4 === "budgets")) || (key4 === "report"))){ -const err59 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data26.browser_attachments !== undefined){ -let data27 = data26.browser_attachments; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err60 = {instancePath:instancePath+"/spawn/resolved/browser_attachments",schemaPath:"#/properties/spawn/properties/resolved/properties/browser_attachments/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(Array.isArray(data27)){ -const len3 = data27.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data27[i3] !== "string"){ -const err61 = {instancePath:instancePath+"/spawn/resolved/browser_attachments/" + i3,schemaPath:"#/properties/spawn/properties/resolved/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -} -} -if(data26.definition !== undefined){ -if(typeof data26.definition !== "string"){ -const err62 = {instancePath:instancePath+"/spawn/resolved/definition",schemaPath:"#/properties/spawn/properties/resolved/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data26.modules !== undefined){ -let data30 = data26.modules; -if((data30 !== null) && (!(Array.isArray(data30)))){ -const err63 = {instancePath:instancePath+"/spawn/resolved/modules",schemaPath:"#/properties/spawn/properties/resolved/properties/modules/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(Array.isArray(data30)){ -const len4 = data30.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data30[i4] !== "string"){ -const err64 = {instancePath:instancePath+"/spawn/resolved/modules/" + i4,schemaPath:"#/properties/spawn/properties/resolved/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data26.capabilities !== undefined){ -let data32 = data26.capabilities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err65 = {instancePath:instancePath+"/spawn/resolved/capabilities",schemaPath:"#/properties/spawn/properties/resolved/properties/capabilities/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(Array.isArray(data32)){ -const len5 = data32.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data32[i5] !== "string"){ -const err66 = {instancePath:instancePath+"/spawn/resolved/capabilities/" + i5,schemaPath:"#/properties/spawn/properties/resolved/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -} -} -if(data26.tools !== undefined){ -let data34 = data26.tools; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err67 = {instancePath:instancePath+"/spawn/resolved/tools",schemaPath:"#/properties/spawn/properties/resolved/properties/tools/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(Array.isArray(data34)){ -const len6 = data34.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data34[i6] !== "string"){ -const err68 = {instancePath:instancePath+"/spawn/resolved/tools/" + i6,schemaPath:"#/properties/spawn/properties/resolved/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -if(data26.budgets !== undefined){ -let data36 = data26.budgets; -if(data36 && typeof data36 == "object" && !Array.isArray(data36)){ -for(const key5 in data36){ -let data37 = data36[key5]; -if(!((typeof data37 == "number") && (!(data37 % 1) && !isNaN(data37)))){ -const err69 = {instancePath:instancePath+"/spawn/resolved/budgets/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/resolved/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -else { -const err70 = {instancePath:instancePath+"/spawn/resolved/budgets",schemaPath:"#/properties/spawn/properties/resolved/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data26.report !== undefined){ -if(typeof data26.report !== "string"){ -const err71 = {instancePath:instancePath+"/spawn/resolved/report",schemaPath:"#/properties/spawn/properties/resolved/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -} -else { -const err72 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -} -if(data.input !== undefined){ -if(typeof data.input !== "string"){ -const err73 = {instancePath:instancePath+"/input",schemaPath:"#/properties/input/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err74 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data41 = data.deadline_millis; -if(typeof data41 === "string"){ -if(!pattern0.test(data41)){ -const err75 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(!(formats0.validate(data41))){ -const err76 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -else { -const err77 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -} -else { -const err78 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -validate77.errors = vErrors; -return errors === 0; -} - -export const HookResultParams = validate78; -const schema79 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"decision":{"type":"string"},"reason":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":false},"context":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HookResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HookResultParams","required":["invocation_id","generation"],"additionalProperties":false}; - -function validate78(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HookResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((((((key0 === "invocation_id") || (key0 === "generation")) || (key0 === "decision")) || (key0 === "reason")) || (key0 === "arguments")) || (key0 === "spawn")) || (key0 === "context")) || (key0 === "error"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err3 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.decision !== undefined){ -if(typeof data.decision !== "string"){ -const err7 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err8 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.spawn !== undefined){ -let data4 = data.spawn; -if((data4 !== null) && (!(data4 && typeof data4 == "object" && !Array.isArray(data4)))){ -const err9 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/type",keyword:"type",params:{type: schema79.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.prompt === undefined){ -const err10 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.name === undefined){ -const err11 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data4.definition === undefined){ -const err12 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data4.capabilities === undefined){ -const err13 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data4.tools === undefined){ -const err14 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data4.budgets === undefined){ -const err15 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data4.report === undefined){ -const err16 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data4.model === undefined){ -const err17 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data4.provider === undefined){ -const err18 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data4.effort === undefined){ -const err19 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -for(const key1 in data4){ -if(!(func2.call(schema79.properties.spawn.properties, key1))){ -const err20 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data4.prompt !== undefined){ -if(typeof data4.prompt !== "string"){ -const err21 = {instancePath:instancePath+"/spawn/prompt",schemaPath:"#/properties/spawn/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err22 = {instancePath:instancePath+"/spawn/name",schemaPath:"#/properties/spawn/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data4.definition !== undefined){ -if(typeof data4.definition !== "string"){ -const err23 = {instancePath:instancePath+"/spawn/definition",schemaPath:"#/properties/spawn/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data4.capabilities !== undefined){ -let data8 = data4.capabilities; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err24 = {instancePath:instancePath+"/spawn/capabilities",schemaPath:"#/properties/spawn/properties/capabilities/type",keyword:"type",params:{type: schema79.properties.spawn.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data8)){ -const len0 = data8.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data8[i0] !== "string"){ -const err25 = {instancePath:instancePath+"/spawn/capabilities/" + i0,schemaPath:"#/properties/spawn/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data4.tools !== undefined){ -let data10 = data4.tools; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err26 = {instancePath:instancePath+"/spawn/tools",schemaPath:"#/properties/spawn/properties/tools/type",keyword:"type",params:{type: schema79.properties.spawn.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data10[i1] !== "string"){ -const err27 = {instancePath:instancePath+"/spawn/tools/" + i1,schemaPath:"#/properties/spawn/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data4.budgets !== undefined){ -let data12 = data4.budgets; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -for(const key2 in data12){ -let data13 = data12[key2]; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err28 = {instancePath:instancePath+"/spawn/budgets/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath:instancePath+"/spawn/budgets",schemaPath:"#/properties/spawn/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data4.report !== undefined){ -if(typeof data4.report !== "string"){ -const err30 = {instancePath:instancePath+"/spawn/report",schemaPath:"#/properties/spawn/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data4.model !== undefined){ -if(typeof data4.model !== "string"){ -const err31 = {instancePath:instancePath+"/spawn/model",schemaPath:"#/properties/spawn/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data4.provider !== undefined){ -if(typeof data4.provider !== "string"){ -const err32 = {instancePath:instancePath+"/spawn/provider",schemaPath:"#/properties/spawn/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data4.effort !== undefined){ -if(typeof data4.effort !== "string"){ -const err33 = {instancePath:instancePath+"/spawn/effort",schemaPath:"#/properties/spawn/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data4.browser_attachments !== undefined){ -let data18 = data4.browser_attachments; -if((data18 !== null) && (!(Array.isArray(data18)))){ -const err34 = {instancePath:instancePath+"/spawn/browser_attachments",schemaPath:"#/properties/spawn/properties/browser_attachments/type",keyword:"type",params:{type: schema79.properties.spawn.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(Array.isArray(data18)){ -const len2 = data18.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data18[i2] !== "string"){ -const err35 = {instancePath:instancePath+"/spawn/browser_attachments/" + i2,schemaPath:"#/properties/spawn/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -} -} -} -if(data.context !== undefined){ -if(typeof data.context !== "string"){ -const err36 = {instancePath:instancePath+"/context",schemaPath:"#/properties/context/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err37 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -} -else { -const err38 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -validate78.errors = vErrors; -return errors === 0; -} - -export const HostAttentionParams = validate79; -const schema80 = {"type":"object","properties":{"after_id":{"type":"string"},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/HostAttentionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostAttentionParams","required":["limit","max_bytes"],"additionalProperties":false}; - -function validate79(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostAttentionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.max_bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "after_id") || (key0 === "limit")) || (key0 === "max_bytes"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.after_id !== undefined){ -if(typeof data.after_id !== "string"){ -const err3 = {instancePath:instancePath+"/after_id",schemaPath:"#/properties/after_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.limit !== undefined){ -let data1 = data.limit; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err4 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data2 = data.max_bytes; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate79.errors = vErrors; -return errors === 0; -} - -export const HostAttentionResult = validate80; -const schema81 = {"type":"object","properties":{"items":{"type":["null","array"],"items":{"type":"object","properties":{"root_id":{"type":"string"},"title":{"type":"string"},"active_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_permissions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":false},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":false}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":false}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":false}}},"additionalProperties":false}},"truncated":{"type":"boolean"}},"required":["root_id","title","active_agents","pending_permissions","questions","truncated"],"additionalProperties":false}},"next_after_id":{"type":"string"},"has_more":{"type":"boolean"},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostAttentionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostAttentionResult","required":["items","has_more","truncated"],"additionalProperties":false}; - -function validate80(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostAttentionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.has_more === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.truncated === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "items") || (key0 === "next_after_id")) || (key0 === "has_more")) || (key0 === "truncated"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.items !== undefined){ -let data0 = data.items; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err4 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema81.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.title === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.active_agents === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "active_agents"},message:"must have required property '"+"active_agents"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.pending_permissions === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_permissions"},message:"must have required property '"+"pending_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.questions === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "questions"},message:"must have required property '"+"questions"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.truncated === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -for(const key1 in data1){ -if(!((((((key1 === "root_id") || (key1 === "title")) || (key1 === "active_agents")) || (key1 === "pending_permissions")) || (key1 === "questions")) || (key1 === "truncated"))){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err12 = {instancePath:instancePath+"/items/" + i0+"/root_id",schemaPath:"#/properties/items/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.title !== undefined){ -if(typeof data1.title !== "string"){ -const err13 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.active_agents !== undefined){ -let data4 = data1.active_agents; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err14 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err15 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -else { -const err16 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data1.pending_permissions !== undefined){ -let data5 = data1.pending_permissions; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -else { -const err19 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.questions !== undefined){ -let data6 = data1.questions; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/questions",schemaPath:"#/properties/items/items/properties/questions/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -let data7 = data6[i1]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -for(const key2 in data7){ -if(!(func2.call(schema81.properties.items.items.properties.questions.items.properties, key2))){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1,schemaPath:"#/properties/items/items/properties/questions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.turn_id !== undefined){ -if(typeof data7.turn_id !== "string"){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/turn_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/root_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/agent_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.sender_agent_id !== undefined){ -if(typeof data7.sender_agent_id !== "string"){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/sender_agent_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.inbox_seq !== undefined){ -let data12 = data7.inbox_seq; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data7.inbox_kind !== undefined){ -if(typeof data7.inbox_kind !== "string"){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_kind",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data7.delivery !== undefined){ -if(typeof data7.delivery !== "string"){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/delivery",schemaPath:"#/properties/items/items/properties/questions/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data7.message_id !== undefined){ -if(typeof data7.message_id !== "string"){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/message_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data7.phase !== undefined){ -if(typeof data7.phase !== "string"){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/phase",schemaPath:"#/properties/items/items/properties/questions/items/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data7.status !== undefined){ -if(typeof data7.status !== "string"){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/status",schemaPath:"#/properties/items/items/properties/questions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data7.terminal_cause !== undefined){ -if(typeof data7.terminal_cause !== "string"){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/terminal_cause",schemaPath:"#/properties/items/items/properties/questions/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data7.command_client_id !== undefined){ -if(typeof data7.command_client_id !== "string"){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command_client_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data7.command_id !== undefined){ -if(typeof data7.command_id !== "string"){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data7.operation_id !== undefined){ -if(typeof data7.operation_id !== "string"){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/operation_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data7.trace_id !== undefined){ -if(typeof data7.trace_id !== "string"){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/trace_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data7.schedule_id !== undefined){ -let data23 = data7.schedule_id; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/schedule_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data7.slot !== undefined){ -if(typeof data7.slot !== "string"){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/slot",schemaPath:"#/properties/items/items/properties/questions/items/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data7.error !== undefined){ -if(typeof data7.error !== "string"){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/error",schemaPath:"#/properties/items/items/properties/questions/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data7.model_call !== undefined){ -let data26 = data7.model_call; -if((data26 !== null) && (!(data26 && typeof data26 == "object" && !Array.isArray(data26)))){ -const err42 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.id === undefined){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data26.logical_id === undefined){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data26.number === undefined){ -const err45 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data26.purpose === undefined){ -const err46 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data26.usage_source === undefined){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data26.cost_source === undefined){ -const err48 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data26.tokens === undefined){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data26.cost_micros === undefined){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data26.elapsed_millis === undefined){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data26.exhausted === undefined){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -for(const key3 in data26){ -if(!(func2.call(schema81.properties.items.items.properties.questions.items.properties.model_call.properties, key3))){ -const err53 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data26.id !== undefined){ -if(typeof data26.id !== "string"){ -const err54 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/id",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data26.logical_id !== undefined){ -if(typeof data26.logical_id !== "string"){ -const err55 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/logical_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data26.number !== undefined){ -let data29 = data26.number; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err56 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/number",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data26.purpose !== undefined){ -if(typeof data26.purpose !== "string"){ -const err57 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/purpose",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data26.usage_source !== undefined){ -if(typeof data26.usage_source !== "string"){ -const err58 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/usage_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data26.cost_source !== undefined){ -if(typeof data26.cost_source !== "string"){ -const err59 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data26.tokens !== undefined){ -let data33 = data26.tokens; -if(typeof data33 === "string"){ -if(!pattern0.test(data33)){ -const err60 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(!(formats0.validate(data33))){ -const err61 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -else { -const err62 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data26.cost_micros !== undefined){ -let data34 = data26.cost_micros; -if(typeof data34 === "string"){ -if(!pattern0.test(data34)){ -const err63 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(!(formats0.validate(data34))){ -const err64 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -else { -const err65 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data26.elapsed_millis !== undefined){ -let data35 = data26.elapsed_millis; -if(typeof data35 === "string"){ -if(!pattern0.test(data35)){ -const err66 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(!(formats0.validate(data35))){ -const err67 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -else { -const err68 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data26.exhausted !== undefined){ -if(typeof data26.exhausted !== "boolean"){ -const err69 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/exhausted",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -} -if(data7.acknowledged_inbox !== undefined){ -let data37 = data7.acknowledged_inbox; -if(Array.isArray(data37)){ -const len2 = data37.length; -for(let i2=0; i2<len2; i2++){ -let data38 = data37[i2]; -if(typeof data38 === "string"){ -if(!pattern0.test(data38)){ -const err70 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(!(formats0.validate(data38))){ -const err71 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -else { -const err72 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -else { -const err73 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox",schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data7.subscription_id !== undefined){ -if(typeof data7.subscription_id !== "string"){ -const err74 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/subscription_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data7.key !== undefined){ -if(typeof data7.key !== "string"){ -const err75 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/key",schemaPath:"#/properties/items/items/properties/questions/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data7.version !== undefined){ -let data41 = data7.version; -if(typeof data41 === "string"){ -if(!pattern0.test(data41)){ -const err76 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -if(!(formats0.validate(data41))){ -const err77 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -else { -const err78 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data7.expected_version !== undefined){ -let data42 = data7.expected_version; -if(typeof data42 === "string"){ -if(!pattern0.test(data42)){ -const err79 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(!(formats0.validate(data42))){ -const err80 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -else { -const err81 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data7.restored !== undefined){ -let data43 = data7.restored; -if((data43 !== null) && (!(Array.isArray(data43)))){ -const err82 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/restored",schemaPath:"#/properties/items/items/properties/questions/items/properties/restored/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(Array.isArray(data43)){ -const len3 = data43.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data43[i3] !== "string"){ -const err83 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/restored/" + i3,schemaPath:"#/properties/items/items/properties/questions/items/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -} -} -if(data7.not_restored !== undefined){ -let data45 = data7.not_restored; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err84 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(Array.isArray(data45)){ -const len4 = data45.length; -for(let i4=0; i4<len4; i4++){ -let data46 = data45[i4]; -if(data46 && typeof data46 == "object" && !Array.isArray(data46)){ -if(data46.name === undefined){ -const err85 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data46.reason === undefined){ -const err86 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -for(const key4 in data46){ -if(!((key4 === "name") || (key4 === "reason"))){ -const err87 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data46.name !== undefined){ -if(typeof data46.name !== "string"){ -const err88 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4+"/name",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data46.reason !== undefined){ -if(typeof data46.reason !== "string"){ -const err89 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4+"/reason",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -} -else { -const err90 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -} -if(data7.attempt !== undefined){ -if(typeof data7.attempt !== "string"){ -const err91 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/attempt",schemaPath:"#/properties/items/items/properties/questions/items/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data7.budget_kind !== undefined){ -if(typeof data7.budget_kind !== "string"){ -const err92 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/budget_kind",schemaPath:"#/properties/items/items/properties/questions/items/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data7.amount !== undefined){ -let data51 = data7.amount; -if(typeof data51 === "string"){ -if(!pattern0.test(data51)){ -const err93 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(!(formats0.validate(data51))){ -const err94 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -else { -const err95 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data7.limit !== undefined){ -let data52 = data7.limit; -if(typeof data52 === "string"){ -if(!pattern0.test(data52)){ -const err96 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -if(!(formats0.validate(data52))){ -const err97 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -else { -const err98 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data7.used !== undefined){ -let data53 = data7.used; -if(typeof data53 === "string"){ -if(!pattern0.test(data53)){ -const err99 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -if(!(formats0.validate(data53))){ -const err100 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -else { -const err101 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data7.reserved !== undefined){ -let data54 = data7.reserved; -if(typeof data54 === "string"){ -if(!pattern0.test(data54)){ -const err102 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(!(formats0.validate(data54))){ -const err103 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -else { -const err104 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data7.capability_id !== undefined){ -if(typeof data7.capability_id !== "string"){ -const err105 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/capability_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data7.generation !== undefined){ -let data56 = data7.generation; -if(typeof data56 === "string"){ -if(!pattern0.test(data56)){ -const err106 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(!(formats0.validate(data56))){ -const err107 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -else { -const err108 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data7.permission_id !== undefined){ -if(typeof data7.permission_id !== "string"){ -const err109 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/permission_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data7.operation !== undefined){ -if(typeof data7.operation !== "string"){ -const err110 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/operation",schemaPath:"#/properties/items/items/properties/questions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data7.canonical_path !== undefined){ -if(typeof data7.canonical_path !== "string"){ -const err111 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/canonical_path",schemaPath:"#/properties/items/items/properties/questions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data7.request_digest !== undefined){ -if(typeof data7.request_digest !== "string"){ -const err112 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/request_digest",schemaPath:"#/properties/items/items/properties/questions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data7.command !== undefined){ -if(typeof data7.command !== "string"){ -const err113 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command",schemaPath:"#/properties/items/items/properties/questions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data7.rule !== undefined){ -if(typeof data7.rule !== "string"){ -const err114 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/rule",schemaPath:"#/properties/items/items/properties/questions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data7.rule_source !== undefined){ -if(typeof data7.rule_source !== "string"){ -const err115 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/rule_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data7.question_id !== undefined){ -if(typeof data7.question_id !== "string"){ -const err116 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/question_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data7.question !== undefined){ -if(typeof data7.question !== "string"){ -const err117 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/question",schemaPath:"#/properties/items/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -if(data7.options !== undefined){ -let data66 = data7.options; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err118 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(Array.isArray(data66)){ -const len5 = data66.length; -for(let i5=0; i5<len5; i5++){ -let data67 = data66[i5]; -if(data67 && typeof data67 == "object" && !Array.isArray(data67)){ -if(data67.label === undefined){ -const err119 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5,schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -for(const key5 in data67){ -if(!(((key5 === "label") || (key5 === "description")) || (key5 === "recommended"))){ -const err120 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5,schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -if(data67.label !== undefined){ -if(typeof data67.label !== "string"){ -const err121 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/label",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -if(data67.description !== undefined){ -if(typeof data67.description !== "string"){ -const err122 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/description",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data67.recommended !== undefined){ -if(typeof data67.recommended !== "boolean"){ -const err123 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/recommended",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -} -else { -const err124 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5,schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -} -} -if(data7.multiple !== undefined){ -if(typeof data7.multiple !== "boolean"){ -const err125 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/multiple",schemaPath:"#/properties/items/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data7.questions !== undefined){ -let data72 = data7.questions; -if((data72 !== null) && (!(Array.isArray(data72)))){ -const err126 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(Array.isArray(data72)){ -const len6 = data72.length; -for(let i6=0; i6<len6; i6++){ -let data73 = data72[i6]; -if(data73 && typeof data73 == "object" && !Array.isArray(data73)){ -if(data73.question === undefined){ -const err127 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -for(const key6 in data73){ -if(!(((key6 === "question") || (key6 === "options")) || (key6 === "multiple"))){ -const err128 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data73.question !== undefined){ -if(typeof data73.question !== "string"){ -const err129 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/question",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -if(data73.options !== undefined){ -let data75 = data73.options; -if((data75 !== null) && (!(Array.isArray(data75)))){ -const err130 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -if(Array.isArray(data75)){ -const len7 = data75.length; -for(let i7=0; i7<len7; i7++){ -let data76 = data75[i7]; -if(data76 && typeof data76 == "object" && !Array.isArray(data76)){ -if(data76.label === undefined){ -const err131 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -for(const key7 in data76){ -if(!(((key7 === "label") || (key7 === "description")) || (key7 === "recommended"))){ -const err132 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data76.label !== undefined){ -if(typeof data76.label !== "string"){ -const err133 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/label",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data76.description !== undefined){ -if(typeof data76.description !== "string"){ -const err134 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/description",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data76.recommended !== undefined){ -if(typeof data76.recommended !== "boolean"){ -const err135 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/recommended",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -} -else { -const err136 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -} -} -if(data73.multiple !== undefined){ -if(typeof data73.multiple !== "boolean"){ -const err137 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/multiple",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -} -else { -const err138 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -if(data7.answer !== undefined){ -let data81 = data7.answer; -if((data81 !== null) && (!(Array.isArray(data81)))){ -const err139 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answer",schemaPath:"#/properties/items/items/properties/questions/items/properties/answer/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -if(Array.isArray(data81)){ -const len8 = data81.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data81[i8] !== "string"){ -const err140 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answer/" + i8,schemaPath:"#/properties/items/items/properties/questions/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -} -} -if(data7.dismissed !== undefined){ -if(typeof data7.dismissed !== "boolean"){ -const err141 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/dismissed",schemaPath:"#/properties/items/items/properties/questions/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -if(data7.answers !== undefined){ -let data84 = data7.answers; -if((data84 !== null) && (!(Array.isArray(data84)))){ -const err142 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -if(Array.isArray(data84)){ -const len9 = data84.length; -for(let i9=0; i9<len9; i9++){ -let data85 = data84[i9]; -if(data85 && typeof data85 == "object" && !Array.isArray(data85)){ -for(const key8 in data85){ -if(!((key8 === "answer") || (key8 === "dismissed"))){ -const err143 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9,schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data85.answer !== undefined){ -let data86 = data85.answer; -if((data86 !== null) && (!(Array.isArray(data86)))){ -const err144 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/answer",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(Array.isArray(data86)){ -const len10 = data86.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data86[i10] !== "string"){ -const err145 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/answer/" + i10,schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -} -} -if(data85.dismissed !== undefined){ -if(typeof data85.dismissed !== "boolean"){ -const err146 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/dismissed",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -} -else { -const err147 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9,schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -} -} -} -else { -const err148 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1,schemaPath:"#/properties/items/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -} -} -if(data1.truncated !== undefined){ -if(typeof data1.truncated !== "boolean"){ -const err149 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -} -else { -const err150 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -} -} -if(data.next_after_id !== undefined){ -if(typeof data.next_after_id !== "string"){ -const err151 = {instancePath:instancePath+"/next_after_id",schemaPath:"#/properties/next_after_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err152 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err153 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -} -else { -const err154 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -validate80.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryParams = validate81; -const schema82 = {"type":"object","properties":{"path":{"type":"string"},"after":{"type":"string"},"prefix":{"type":"string"},"show_hidden":{"type":"boolean"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryParams","required":["limit"],"additionalProperties":false}; - -function validate81(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "path") || (key0 === "after")) || (key0 === "prefix")) || (key0 === "show_hidden")) || (key0 === "limit"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err2 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.after !== undefined){ -if(typeof data.after !== "string"){ -const err3 = {instancePath:instancePath+"/after",schemaPath:"#/properties/after/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err4 = {instancePath:instancePath+"/prefix",schemaPath:"#/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.show_hidden !== undefined){ -if(typeof data.show_hidden !== "boolean"){ -const err5 = {instancePath:instancePath+"/show_hidden",schemaPath:"#/properties/show_hidden/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err6 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate81.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryPickParams = validate82; -const schema83 = {"type":"object","properties":{"start":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryPickParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryPickParams","additionalProperties":false}; - -function validate82(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryPickParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "start")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.start !== undefined){ -if(typeof data.start !== "string"){ -const err1 = {instancePath:instancePath+"/start",schemaPath:"#/properties/start/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate82.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryPickResult = validate83; -const schema84 = {"type":"object","properties":{"path":{"type":"string"},"cancelled":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryPickResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryPickResult","required":["cancelled"],"additionalProperties":false}; - -function validate83(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryPickResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cancelled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cancelled"},message:"must have required property '"+"cancelled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "path") || (key0 === "cancelled"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err2 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cancelled !== undefined){ -if(typeof data.cancelled !== "boolean"){ -const err3 = {instancePath:instancePath+"/cancelled",schemaPath:"#/properties/cancelled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate83.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryResult = validate84; -const schema85 = {"type":"object","properties":{"path":{"type":"string"},"parent":{"type":"string"},"entries":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"}},"required":["name","path"],"additionalProperties":false}},"next_after":{"type":"string"},"has_more":{"type":"boolean"},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryResult","required":["path","parent","entries","has_more","truncated"],"additionalProperties":false}; - -function validate84(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.parent === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "parent"},message:"must have required property '"+"parent"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.entries === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "entries"},message:"must have required property '"+"entries"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.truncated === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "path") || (key0 === "parent")) || (key0 === "entries")) || (key0 === "next_after")) || (key0 === "has_more")) || (key0 === "truncated"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err6 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.parent !== undefined){ -if(typeof data.parent !== "string"){ -const err7 = {instancePath:instancePath+"/parent",schemaPath:"#/properties/parent/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.entries !== undefined){ -let data2 = data.entries; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err8 = {instancePath:instancePath+"/entries",schemaPath:"#/properties/entries/type",keyword:"type",params:{type: schema85.properties.entries.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -let data3 = data2[i0]; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.name === undefined){ -const err9 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data3.path === undefined){ -const err10 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -for(const key1 in data3){ -if(!((key1 === "name") || (key1 === "path"))){ -const err11 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data3.name !== undefined){ -if(typeof data3.name !== "string"){ -const err12 = {instancePath:instancePath+"/entries/" + i0+"/name",schemaPath:"#/properties/entries/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data3.path !== undefined){ -if(typeof data3.path !== "string"){ -const err13 = {instancePath:instancePath+"/entries/" + i0+"/path",schemaPath:"#/properties/entries/items/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.next_after !== undefined){ -if(typeof data.next_after !== "string"){ -const err15 = {instancePath:instancePath+"/next_after",schemaPath:"#/properties/next_after/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err16 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err17 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -validate84.errors = vErrors; -return errors === 0; -} - -export const HostSkillCompletionParams = validate85; -const schema86 = {"$id":"https://whip.dev/protocol/v6/HostSkillCompletionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostSkillCompletionParams","allOf":[{"type":"object","properties":{"scope":{"type":"string"},"cwd":{"type":"string"},"definition":{"type":"string"},"permission_mode":{"type":"string"},"prefix":{"type":"string"},"limit":{"type":"integer"}},"required":["prefix","limit"],"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"cwd":{"type":"string","pattern":"^[\\s\\S]+$"},"scope":{"type":"string","enum":[""]}},"required":["cwd"]},{"type":"object","properties":{"cwd":{"type":"string","enum":[""]},"scope":{"type":"string","enum":["global"]}},"required":["scope"]}]}]}; -const pattern80 = new RegExp("^[\\s\\S]+$", "u"); - -function validate85(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostSkillCompletionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.prefix === undefined){ -const err0 = {instancePath,schemaPath:"#/allOf/0/required",keyword:"required",params:{missingProperty: "prefix"},message:"must have required property '"+"prefix"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.limit === undefined){ -const err1 = {instancePath,schemaPath:"#/allOf/0/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "scope") || (key0 === "cwd")) || (key0 === "definition")) || (key0 === "permission_mode")) || (key0 === "prefix")) || (key0 === "limit"))){ -const err2 = {instancePath,schemaPath:"#/allOf/0/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.scope !== undefined){ -if(typeof data.scope !== "string"){ -const err3 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/0/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err4 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/0/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err5 = {instancePath:instancePath+"/definition",schemaPath:"#/allOf/0/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err6 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/allOf/0/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err7 = {instancePath:instancePath+"/prefix",schemaPath:"#/allOf/0/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.limit !== undefined){ -let data5 = data.limit; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err8 = {instancePath:instancePath+"/limit",schemaPath:"#/allOf/0/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/allOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -const _errs16 = errors; -let valid2 = false; -let passing0 = null; -const _errs17 = errors; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cwd === undefined){ -const err10 = {instancePath,schemaPath:"#/allOf/1/oneOf/0/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.cwd !== undefined){ -let data6 = data.cwd; -if(typeof data6 === "string"){ -if(!pattern80.test(data6)){ -const err11 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/0/properties/cwd/pattern",keyword:"pattern",params:{pattern: "^[\\s\\S]+$"},message:"must match pattern \""+"^[\\s\\S]+$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -else { -const err12 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/0/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.scope !== undefined){ -let data7 = data.scope; -if(typeof data7 !== "string"){ -const err13 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/0/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(!(data7 === "")){ -const err14 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/0/properties/scope/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[0].properties.scope.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath,schemaPath:"#/allOf/1/oneOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -var _valid0 = _errs17 === errors; -if(_valid0){ -valid2 = true; -passing0 = 0; -} -const _errs23 = errors; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.scope === undefined){ -const err16 = {instancePath,schemaPath:"#/allOf/1/oneOf/1/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data.cwd !== undefined){ -let data8 = data.cwd; -if(typeof data8 !== "string"){ -const err17 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/1/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(!(data8 === "")){ -const err18 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/1/properties/cwd/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[1].properties.cwd.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.scope !== undefined){ -let data9 = data.scope; -if(typeof data9 !== "string"){ -const err19 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/1/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(!(data9 === "global")){ -const err20 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/1/properties/scope/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[1].properties.scope.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath,schemaPath:"#/allOf/1/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -var _valid0 = _errs23 === errors; -if(_valid0 && valid2){ -valid2 = false; -passing0 = [passing0, 1]; -} -else { -if(_valid0){ -valid2 = true; -passing0 = 1; -} -} -if(!valid2){ -const err22 = {instancePath,schemaPath:"#/allOf/1/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -else { -errors = _errs16; -if(vErrors !== null){ -if(_errs16){ -vErrors.length = _errs16; -} -else { -vErrors = null; -} -} -} -validate85.errors = vErrors; -return errors === 0; -} - -export const HostThemeResolveParams = validate86; -const schema87 = {"type":"object","properties":{"name":{"type":"string"},"json":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HostThemeResolveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostThemeResolveParams","additionalProperties":false}; - -function validate86(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostThemeResolveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((key0 === "name") || (key0 === "json"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err1 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.json !== undefined){ -if(typeof data.json !== "string"){ -const err2 = {instancePath:instancePath+"/json",schemaPath:"#/properties/json/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate86.errors = vErrors; -return errors === 0; -} - -export const IDParams = validate87; -const schema88 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/IDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"IDParams","required":["id"],"additionalProperties":false}; - -function validate87(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/IDParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate87.errors = vErrors; -return errors === 0; -} - -export const InboxControlResult = validate88; -const schema89 = {"type":"object","properties":{"agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/InboxControlResult","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxControlResult","required":["agent_id","inbox_seq","status"],"additionalProperties":false}; - -function validate88(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxControlResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.agent_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.status === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "agent_id") || (key0 === "inbox_seq")) || (key0 === "status"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err4 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err8 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate88.errors = vErrors; -return errors === 0; -} - -export const InboxRemoveParams = validate89; -const schema90 = {"type":"object","properties":{"id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/InboxRemoveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxRemoveParams","required":["id","inbox_seq"],"additionalProperties":false}; - -function validate89(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxRemoveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "inbox_seq"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate89.errors = vErrors; -return errors === 0; -} - -export const InboxSteerParams = validate90; -const schema91 = {"type":"object","properties":{"id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"turn_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/InboxSteerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxSteerParams","required":["id","inbox_seq","turn_id"],"additionalProperties":false}; - -function validate90(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxSteerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.turn_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "inbox_seq")) || (key0 === "turn_id"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err8 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate90.errors = vErrors; -return errors === 0; -} - -export const InitializeParams = validate91; -const schema92 = {"type":"object","properties":{"protocol_major":{"type":"integer"},"build_id":{"type":"string"},"client_kind":{"type":"string"},"client_id":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/InitializeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InitializeParams","required":["protocol_major","build_id","client_kind","client_id"],"additionalProperties":false}; - -function validate91(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InitializeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.protocol_major === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_major"},message:"must have required property '"+"protocol_major"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.build_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.client_kind === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "client_kind"},message:"must have required property '"+"client_kind"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.client_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "client_id"},message:"must have required property '"+"client_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "protocol_major") || (key0 === "build_id")) || (key0 === "client_kind")) || (key0 === "client_id")) || (key0 === "capabilities"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.protocol_major !== undefined){ -let data0 = data.protocol_major; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err5 = {instancePath:instancePath+"/protocol_major",schemaPath:"#/properties/protocol_major/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err6 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.client_kind !== undefined){ -if(typeof data.client_kind !== "string"){ -const err7 = {instancePath:instancePath+"/client_kind",schemaPath:"#/properties/client_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.client_id !== undefined){ -if(typeof data.client_id !== "string"){ -const err8 = {instancePath:instancePath+"/client_id",schemaPath:"#/properties/client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data4 = data.capabilities; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err9 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema92.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err10 = {instancePath:instancePath+"/capabilities/" + i0,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate91.errors = vErrors; -return errors === 0; -} - -export const InitializeResult = validate92; -const schema93 = {"type":"object","properties":{"execution_engines":{"type":["null","array"],"items":{"type":"object","properties":{"bridge_sha256":{"type":"string"},"build":{"type":"string"},"abi":{"type":"string"},"profile":{"type":"string"},"fidelity":{"type":"string"},"guide_sha256":{"type":"string"},"features":{"type":["null","array"],"items":{"type":"string"}},"default_limits":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"id":{"type":"string"},"language":{"type":"string"},"label":{"type":"string"}},"required":["id","language","label"],"additionalProperties":false}},"default_execution_engine":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"surface":{"type":"string"},"execution":{"type":"string"},"permission":{"type":"string"},"sensitive":{"type":"boolean"}},"required":["name","surface","execution","permission"],"additionalProperties":false}},"limits":{"type":"object","properties":{"frame_bytes":{"type":"integer"},"connections":{"type":"integer"},"in_flight_requests":{"type":"integer"},"outbound_messages":{"type":"integer"},"outbound_bytes":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_subscriptions":{"type":"integer"},"content_chunk_bytes":{"type":"integer"},"upload_bytes":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["frame_bytes","connections","in_flight_requests","outbound_messages","outbound_bytes","root_subscriptions","content_chunk_bytes","upload_bytes"],"additionalProperties":false},"negotiated_capabilities":{"type":["null","array"],"items":{"type":"string"}},"protocol_minor":{"type":"integer"},"runtime_id":{"type":"string"},"connection_id":{"type":"string"},"host_platform":{"type":"string"},"host_architecture":{"type":"string"},"network_endpoint":{"type":"string"},"protocol_major":{"type":"integer"},"build_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pid":{"type":"integer"},"started_at":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/InitializeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"InitializeResult","required":["execution_engines","default_execution_engine","operations","limits","negotiated_capabilities","protocol_minor","runtime_id","connection_id","host_platform","host_architecture","protocol_major","build_id","generation","capabilities"],"additionalProperties":false}; - -function validate92(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InitializeResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.execution_engines === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "execution_engines"},message:"must have required property '"+"execution_engines"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.default_execution_engine === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_execution_engine"},message:"must have required property '"+"default_execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.operations === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limits === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limits"},message:"must have required property '"+"limits"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.negotiated_capabilities === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "negotiated_capabilities"},message:"must have required property '"+"negotiated_capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.protocol_minor === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_minor"},message:"must have required property '"+"protocol_minor"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.runtime_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.connection_id === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "connection_id"},message:"must have required property '"+"connection_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.host_platform === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "host_platform"},message:"must have required property '"+"host_platform"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.host_architecture === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "host_architecture"},message:"must have required property '"+"host_architecture"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.protocol_major === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_major"},message:"must have required property '"+"protocol_major"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.build_id === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.generation === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.capabilities === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema93.properties, key0))){ -const err14 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.execution_engines !== undefined){ -let data0 = data.execution_engines; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err15 = {instancePath:instancePath+"/execution_engines",schemaPath:"#/properties/execution_engines/type",keyword:"type",params:{type: schema93.properties.execution_engines.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err16 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data1.language === undefined){ -const err17 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "language"},message:"must have required property '"+"language"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data1.label === undefined){ -const err18 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -for(const key1 in data1){ -if(!(func2.call(schema93.properties.execution_engines.items.properties, key1))){ -const err19 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.bridge_sha256 !== undefined){ -if(typeof data1.bridge_sha256 !== "string"){ -const err20 = {instancePath:instancePath+"/execution_engines/" + i0+"/bridge_sha256",schemaPath:"#/properties/execution_engines/items/properties/bridge_sha256/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data1.build !== undefined){ -if(typeof data1.build !== "string"){ -const err21 = {instancePath:instancePath+"/execution_engines/" + i0+"/build",schemaPath:"#/properties/execution_engines/items/properties/build/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data1.abi !== undefined){ -if(typeof data1.abi !== "string"){ -const err22 = {instancePath:instancePath+"/execution_engines/" + i0+"/abi",schemaPath:"#/properties/execution_engines/items/properties/abi/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data1.profile !== undefined){ -if(typeof data1.profile !== "string"){ -const err23 = {instancePath:instancePath+"/execution_engines/" + i0+"/profile",schemaPath:"#/properties/execution_engines/items/properties/profile/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data1.fidelity !== undefined){ -if(typeof data1.fidelity !== "string"){ -const err24 = {instancePath:instancePath+"/execution_engines/" + i0+"/fidelity",schemaPath:"#/properties/execution_engines/items/properties/fidelity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data1.guide_sha256 !== undefined){ -if(typeof data1.guide_sha256 !== "string"){ -const err25 = {instancePath:instancePath+"/execution_engines/" + i0+"/guide_sha256",schemaPath:"#/properties/execution_engines/items/properties/guide_sha256/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data1.features !== undefined){ -let data8 = data1.features; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err26 = {instancePath:instancePath+"/execution_engines/" + i0+"/features",schemaPath:"#/properties/execution_engines/items/properties/features/type",keyword:"type",params:{type: schema93.properties.execution_engines.items.properties.features.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err27 = {instancePath:instancePath+"/execution_engines/" + i0+"/features/" + i1,schemaPath:"#/properties/execution_engines/items/properties/features/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data1.default_limits !== undefined){ -let data10 = data1.default_limits; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -for(const key2 in data10){ -let data11 = data10[key2]; -if(!((typeof data11 == "number") && (!(data11 % 1) && !isNaN(data11)))){ -const err28 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/execution_engines/items/properties/default_limits/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(typeof data11 == "number"){ -if(data11 < 0 || isNaN(data11)){ -const err29 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/execution_engines/items/properties/default_limits/additionalProperties/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -} -else { -const err30 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits",schemaPath:"#/properties/execution_engines/items/properties/default_limits/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err31 = {instancePath:instancePath+"/execution_engines/" + i0+"/id",schemaPath:"#/properties/execution_engines/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data1.language !== undefined){ -if(typeof data1.language !== "string"){ -const err32 = {instancePath:instancePath+"/execution_engines/" + i0+"/language",schemaPath:"#/properties/execution_engines/items/properties/language/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err33 = {instancePath:instancePath+"/execution_engines/" + i0+"/label",schemaPath:"#/properties/execution_engines/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -else { -const err34 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -} -if(data.default_execution_engine !== undefined){ -if(typeof data.default_execution_engine !== "string"){ -const err35 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data.operations !== undefined){ -let data16 = data.operations; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err36 = {instancePath:instancePath+"/operations",schemaPath:"#/properties/operations/type",keyword:"type",params:{type: schema93.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(Array.isArray(data16)){ -const len2 = data16.length; -for(let i2=0; i2<len2; i2++){ -let data17 = data16[i2]; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.name === undefined){ -const err37 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data17.surface === undefined){ -const err38 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data17.execution === undefined){ -const err39 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "execution"},message:"must have required property '"+"execution"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data17.permission === undefined){ -const err40 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "permission"},message:"must have required property '"+"permission"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -for(const key3 in data17){ -if(!(((((key3 === "name") || (key3 === "surface")) || (key3 === "execution")) || (key3 === "permission")) || (key3 === "sensitive"))){ -const err41 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data17.name !== undefined){ -if(typeof data17.name !== "string"){ -const err42 = {instancePath:instancePath+"/operations/" + i2+"/name",schemaPath:"#/properties/operations/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data17.surface !== undefined){ -if(typeof data17.surface !== "string"){ -const err43 = {instancePath:instancePath+"/operations/" + i2+"/surface",schemaPath:"#/properties/operations/items/properties/surface/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data17.execution !== undefined){ -if(typeof data17.execution !== "string"){ -const err44 = {instancePath:instancePath+"/operations/" + i2+"/execution",schemaPath:"#/properties/operations/items/properties/execution/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.permission !== undefined){ -if(typeof data17.permission !== "string"){ -const err45 = {instancePath:instancePath+"/operations/" + i2+"/permission",schemaPath:"#/properties/operations/items/properties/permission/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.sensitive !== undefined){ -if(typeof data17.sensitive !== "boolean"){ -const err46 = {instancePath:instancePath+"/operations/" + i2+"/sensitive",schemaPath:"#/properties/operations/items/properties/sensitive/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -else { -const err47 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -} -if(data.limits !== undefined){ -let data23 = data.limits; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.frame_bytes === undefined){ -const err48 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "frame_bytes"},message:"must have required property '"+"frame_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data23.connections === undefined){ -const err49 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "connections"},message:"must have required property '"+"connections"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data23.in_flight_requests === undefined){ -const err50 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "in_flight_requests"},message:"must have required property '"+"in_flight_requests"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data23.outbound_messages === undefined){ -const err51 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "outbound_messages"},message:"must have required property '"+"outbound_messages"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data23.outbound_bytes === undefined){ -const err52 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "outbound_bytes"},message:"must have required property '"+"outbound_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data23.root_subscriptions === undefined){ -const err53 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "root_subscriptions"},message:"must have required property '"+"root_subscriptions"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data23.content_chunk_bytes === undefined){ -const err54 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "content_chunk_bytes"},message:"must have required property '"+"content_chunk_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data23.upload_bytes === undefined){ -const err55 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "upload_bytes"},message:"must have required property '"+"upload_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -for(const key4 in data23){ -if(!((((((((key4 === "frame_bytes") || (key4 === "connections")) || (key4 === "in_flight_requests")) || (key4 === "outbound_messages")) || (key4 === "outbound_bytes")) || (key4 === "root_subscriptions")) || (key4 === "content_chunk_bytes")) || (key4 === "upload_bytes"))){ -const err56 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data23.frame_bytes !== undefined){ -let data24 = data23.frame_bytes; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err57 = {instancePath:instancePath+"/limits/frame_bytes",schemaPath:"#/properties/limits/properties/frame_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data23.connections !== undefined){ -let data25 = data23.connections; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err58 = {instancePath:instancePath+"/limits/connections",schemaPath:"#/properties/limits/properties/connections/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data23.in_flight_requests !== undefined){ -let data26 = data23.in_flight_requests; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err59 = {instancePath:instancePath+"/limits/in_flight_requests",schemaPath:"#/properties/limits/properties/in_flight_requests/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data23.outbound_messages !== undefined){ -let data27 = data23.outbound_messages; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err60 = {instancePath:instancePath+"/limits/outbound_messages",schemaPath:"#/properties/limits/properties/outbound_messages/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data23.outbound_bytes !== undefined){ -let data28 = data23.outbound_bytes; -if(typeof data28 === "string"){ -if(!pattern0.test(data28)){ -const err61 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(!(formats0.validate(data28))){ -const err62 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -else { -const err63 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data23.root_subscriptions !== undefined){ -let data29 = data23.root_subscriptions; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err64 = {instancePath:instancePath+"/limits/root_subscriptions",schemaPath:"#/properties/limits/properties/root_subscriptions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data23.content_chunk_bytes !== undefined){ -let data30 = data23.content_chunk_bytes; -if(!((typeof data30 == "number") && (!(data30 % 1) && !isNaN(data30)))){ -const err65 = {instancePath:instancePath+"/limits/content_chunk_bytes",schemaPath:"#/properties/limits/properties/content_chunk_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data23.upload_bytes !== undefined){ -let data31 = data23.upload_bytes; -if(typeof data31 === "string"){ -if(!pattern0.test(data31)){ -const err66 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(!(formats0.validate(data31))){ -const err67 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -else { -const err68 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -else { -const err69 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data.negotiated_capabilities !== undefined){ -let data32 = data.negotiated_capabilities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err70 = {instancePath:instancePath+"/negotiated_capabilities",schemaPath:"#/properties/negotiated_capabilities/type",keyword:"type",params:{type: schema93.properties.negotiated_capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(Array.isArray(data32)){ -const len3 = data32.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data32[i3] !== "string"){ -const err71 = {instancePath:instancePath+"/negotiated_capabilities/" + i3,schemaPath:"#/properties/negotiated_capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -} -} -if(data.protocol_minor !== undefined){ -let data34 = data.protocol_minor; -if(!((typeof data34 == "number") && (!(data34 % 1) && !isNaN(data34)))){ -const err72 = {instancePath:instancePath+"/protocol_minor",schemaPath:"#/properties/protocol_minor/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data.runtime_id !== undefined){ -if(typeof data.runtime_id !== "string"){ -const err73 = {instancePath:instancePath+"/runtime_id",schemaPath:"#/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.connection_id !== undefined){ -if(typeof data.connection_id !== "string"){ -const err74 = {instancePath:instancePath+"/connection_id",schemaPath:"#/properties/connection_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.host_platform !== undefined){ -if(typeof data.host_platform !== "string"){ -const err75 = {instancePath:instancePath+"/host_platform",schemaPath:"#/properties/host_platform/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.host_architecture !== undefined){ -if(typeof data.host_architecture !== "string"){ -const err76 = {instancePath:instancePath+"/host_architecture",schemaPath:"#/properties/host_architecture/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.network_endpoint !== undefined){ -if(typeof data.network_endpoint !== "string"){ -const err77 = {instancePath:instancePath+"/network_endpoint",schemaPath:"#/properties/network_endpoint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.protocol_major !== undefined){ -let data40 = data.protocol_major; -if(!((typeof data40 == "number") && (!(data40 % 1) && !isNaN(data40)))){ -const err78 = {instancePath:instancePath+"/protocol_major",schemaPath:"#/properties/protocol_major/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err79 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data.generation !== undefined){ -let data42 = data.generation; -if(typeof data42 === "string"){ -if(!pattern0.test(data42)){ -const err80 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(!(formats0.validate(data42))){ -const err81 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -else { -const err82 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -if(data.pid !== undefined){ -let data43 = data.pid; -if(!((typeof data43 == "number") && (!(data43 % 1) && !isNaN(data43)))){ -const err83 = {instancePath:instancePath+"/pid",schemaPath:"#/properties/pid/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data.started_at !== undefined){ -if(typeof data.started_at !== "string"){ -const err84 = {instancePath:instancePath+"/started_at",schemaPath:"#/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data45 = data.capabilities; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err85 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema93.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(Array.isArray(data45)){ -const len4 = data45.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data45[i4] !== "string"){ -const err86 = {instancePath:instancePath+"/capabilities/" + i4,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -} -} -} -else { -const err87 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -validate92.errors = vErrors; -return errors === 0; -} - -export const LSPListResult = validate93; -const schema94 = {"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"root":{"type":"string"},"state":{"type":"string"},"error":{"type":"string"}},"required":["name","state"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/LSPListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"LSPListResult"}; - -function validate93(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/LSPListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema94.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.name === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.state === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data0){ -if(!((((key0 === "name") || (key0 === "root")) || (key0 === "state")) || (key0 === "error"))){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err4 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.root !== undefined){ -if(typeof data0.root !== "string"){ -const err5 = {instancePath:instancePath+"/" + i0+"/root",schemaPath:"#/items/properties/root/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.state !== undefined){ -if(typeof data0.state !== "string"){ -const err6 = {instancePath:instancePath+"/" + i0+"/state",schemaPath:"#/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.error !== undefined){ -if(typeof data0.error !== "string"){ -const err7 = {instancePath:instancePath+"/" + i0+"/error",schemaPath:"#/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -validate93.errors = vErrors; -return errors === 0; -} - -export const LifecycleEvent = validate94; -const schema95 = {"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":false},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":false}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":false}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/LifecycleEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"LifecycleEvent","additionalProperties":false}; - -function validate94(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/LifecycleEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(func2.call(schema95.properties, key0))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err1 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err3 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.sender_agent_id !== undefined){ -if(typeof data.sender_agent_id !== "string"){ -const err4 = {instancePath:instancePath+"/sender_agent_id",schemaPath:"#/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data4 = data.inbox_seq; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.inbox_kind !== undefined){ -if(typeof data.inbox_kind !== "string"){ -const err8 = {instancePath:instancePath+"/inbox_kind",schemaPath:"#/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err9 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.message_id !== undefined){ -if(typeof data.message_id !== "string"){ -const err10 = {instancePath:instancePath+"/message_id",schemaPath:"#/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.phase !== undefined){ -if(typeof data.phase !== "string"){ -const err11 = {instancePath:instancePath+"/phase",schemaPath:"#/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err12 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.terminal_cause !== undefined){ -if(typeof data.terminal_cause !== "string"){ -const err13 = {instancePath:instancePath+"/terminal_cause",schemaPath:"#/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.command_client_id !== undefined){ -if(typeof data.command_client_id !== "string"){ -const err14 = {instancePath:instancePath+"/command_client_id",schemaPath:"#/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err15 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err16 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err17 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.schedule_id !== undefined){ -let data15 = data.schedule_id; -if(!((typeof data15 == "number") && (!(data15 % 1) && !isNaN(data15)))){ -const err18 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.slot !== undefined){ -if(typeof data.slot !== "string"){ -const err19 = {instancePath:instancePath+"/slot",schemaPath:"#/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err20 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.model_call !== undefined){ -let data18 = data.model_call; -if((data18 !== null) && (!(data18 && typeof data18 == "object" && !Array.isArray(data18)))){ -const err21 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/type",keyword:"type",params:{type: schema95.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -if(data18.id === undefined){ -const err22 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data18.logical_id === undefined){ -const err23 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data18.number === undefined){ -const err24 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data18.purpose === undefined){ -const err25 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data18.usage_source === undefined){ -const err26 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data18.cost_source === undefined){ -const err27 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data18.tokens === undefined){ -const err28 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data18.cost_micros === undefined){ -const err29 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data18.elapsed_millis === undefined){ -const err30 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data18.exhausted === undefined){ -const err31 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -for(const key1 in data18){ -if(!(func2.call(schema95.properties.model_call.properties, key1))){ -const err32 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data18.id !== undefined){ -if(typeof data18.id !== "string"){ -const err33 = {instancePath:instancePath+"/model_call/id",schemaPath:"#/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data18.logical_id !== undefined){ -if(typeof data18.logical_id !== "string"){ -const err34 = {instancePath:instancePath+"/model_call/logical_id",schemaPath:"#/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data18.number !== undefined){ -let data21 = data18.number; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err35 = {instancePath:instancePath+"/model_call/number",schemaPath:"#/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data18.purpose !== undefined){ -if(typeof data18.purpose !== "string"){ -const err36 = {instancePath:instancePath+"/model_call/purpose",schemaPath:"#/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data18.usage_source !== undefined){ -if(typeof data18.usage_source !== "string"){ -const err37 = {instancePath:instancePath+"/model_call/usage_source",schemaPath:"#/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data18.cost_source !== undefined){ -if(typeof data18.cost_source !== "string"){ -const err38 = {instancePath:instancePath+"/model_call/cost_source",schemaPath:"#/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data18.tokens !== undefined){ -let data25 = data18.tokens; -if(typeof data25 === "string"){ -if(!pattern0.test(data25)){ -const err39 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(!(formats0.validate(data25))){ -const err40 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -else { -const err41 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data18.cost_micros !== undefined){ -let data26 = data18.cost_micros; -if(typeof data26 === "string"){ -if(!pattern0.test(data26)){ -const err42 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(!(formats0.validate(data26))){ -const err43 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -else { -const err44 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data18.elapsed_millis !== undefined){ -let data27 = data18.elapsed_millis; -if(typeof data27 === "string"){ -if(!pattern0.test(data27)){ -const err45 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(!(formats0.validate(data27))){ -const err46 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -else { -const err47 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data18.exhausted !== undefined){ -if(typeof data18.exhausted !== "boolean"){ -const err48 = {instancePath:instancePath+"/model_call/exhausted",schemaPath:"#/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -} -} -if(data.acknowledged_inbox !== undefined){ -let data29 = data.acknowledged_inbox; -if(Array.isArray(data29)){ -const len0 = data29.length; -for(let i0=0; i0<len0; i0++){ -let data30 = data29[i0]; -if(typeof data30 === "string"){ -if(!pattern0.test(data30)){ -const err49 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(!(formats0.validate(data30))){ -const err50 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -else { -const err51 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -else { -const err52 = {instancePath:instancePath+"/acknowledged_inbox",schemaPath:"#/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err53 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err54 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data.version !== undefined){ -let data33 = data.version; -if(typeof data33 === "string"){ -if(!pattern0.test(data33)){ -const err55 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(!(formats0.validate(data33))){ -const err56 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -else { -const err57 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data.expected_version !== undefined){ -let data34 = data.expected_version; -if(typeof data34 === "string"){ -if(!pattern0.test(data34)){ -const err58 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(!(formats0.validate(data34))){ -const err59 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -else { -const err60 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data.restored !== undefined){ -let data35 = data.restored; -if((data35 !== null) && (!(Array.isArray(data35)))){ -const err61 = {instancePath:instancePath+"/restored",schemaPath:"#/properties/restored/type",keyword:"type",params:{type: schema95.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(Array.isArray(data35)){ -const len1 = data35.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data35[i1] !== "string"){ -const err62 = {instancePath:instancePath+"/restored/" + i1,schemaPath:"#/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -} -} -if(data.not_restored !== undefined){ -let data37 = data.not_restored; -if((data37 !== null) && (!(Array.isArray(data37)))){ -const err63 = {instancePath:instancePath+"/not_restored",schemaPath:"#/properties/not_restored/type",keyword:"type",params:{type: schema95.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(Array.isArray(data37)){ -const len2 = data37.length; -for(let i2=0; i2<len2; i2++){ -let data38 = data37[i2]; -if(data38 && typeof data38 == "object" && !Array.isArray(data38)){ -if(data38.name === undefined){ -const err64 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data38.reason === undefined){ -const err65 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -for(const key2 in data38){ -if(!((key2 === "name") || (key2 === "reason"))){ -const err66 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data38.name !== undefined){ -if(typeof data38.name !== "string"){ -const err67 = {instancePath:instancePath+"/not_restored/" + i2+"/name",schemaPath:"#/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data38.reason !== undefined){ -if(typeof data38.reason !== "string"){ -const err68 = {instancePath:instancePath+"/not_restored/" + i2+"/reason",schemaPath:"#/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -else { -const err69 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -} -if(data.attempt !== undefined){ -if(typeof data.attempt !== "string"){ -const err70 = {instancePath:instancePath+"/attempt",schemaPath:"#/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.budget_kind !== undefined){ -if(typeof data.budget_kind !== "string"){ -const err71 = {instancePath:instancePath+"/budget_kind",schemaPath:"#/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.amount !== undefined){ -let data43 = data.amount; -if(typeof data43 === "string"){ -if(!pattern0.test(data43)){ -const err72 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(!(formats0.validate(data43))){ -const err73 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -else { -const err74 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.limit !== undefined){ -let data44 = data.limit; -if(typeof data44 === "string"){ -if(!pattern0.test(data44)){ -const err75 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(!(formats0.validate(data44))){ -const err76 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -else { -const err77 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.used !== undefined){ -let data45 = data.used; -if(typeof data45 === "string"){ -if(!pattern0.test(data45)){ -const err78 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(!(formats0.validate(data45))){ -const err79 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -else { -const err80 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.reserved !== undefined){ -let data46 = data.reserved; -if(typeof data46 === "string"){ -if(!pattern0.test(data46)){ -const err81 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(!(formats0.validate(data46))){ -const err82 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -else { -const err83 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data.capability_id !== undefined){ -if(typeof data.capability_id !== "string"){ -const err84 = {instancePath:instancePath+"/capability_id",schemaPath:"#/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data.generation !== undefined){ -let data48 = data.generation; -if(typeof data48 === "string"){ -if(!pattern0.test(data48)){ -const err85 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(!(formats0.validate(data48))){ -const err86 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -else { -const err87 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data.permission_id !== undefined){ -if(typeof data.permission_id !== "string"){ -const err88 = {instancePath:instancePath+"/permission_id",schemaPath:"#/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err89 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data.canonical_path !== undefined){ -if(typeof data.canonical_path !== "string"){ -const err90 = {instancePath:instancePath+"/canonical_path",schemaPath:"#/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data.request_digest !== undefined){ -if(typeof data.request_digest !== "string"){ -const err91 = {instancePath:instancePath+"/request_digest",schemaPath:"#/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data.command !== undefined){ -if(typeof data.command !== "string"){ -const err92 = {instancePath:instancePath+"/command",schemaPath:"#/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data.rule !== undefined){ -if(typeof data.rule !== "string"){ -const err93 = {instancePath:instancePath+"/rule",schemaPath:"#/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data.rule_source !== undefined){ -if(typeof data.rule_source !== "string"){ -const err94 = {instancePath:instancePath+"/rule_source",schemaPath:"#/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data.question_id !== undefined){ -if(typeof data.question_id !== "string"){ -const err95 = {instancePath:instancePath+"/question_id",schemaPath:"#/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data.question !== undefined){ -if(typeof data.question !== "string"){ -const err96 = {instancePath:instancePath+"/question",schemaPath:"#/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data.options !== undefined){ -let data58 = data.options; -if((data58 !== null) && (!(Array.isArray(data58)))){ -const err97 = {instancePath:instancePath+"/options",schemaPath:"#/properties/options/type",keyword:"type",params:{type: schema95.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -if(Array.isArray(data58)){ -const len3 = data58.length; -for(let i3=0; i3<len3; i3++){ -let data59 = data58[i3]; -if(data59 && typeof data59 == "object" && !Array.isArray(data59)){ -if(data59.label === undefined){ -const err98 = {instancePath:instancePath+"/options/" + i3,schemaPath:"#/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -for(const key3 in data59){ -if(!(((key3 === "label") || (key3 === "description")) || (key3 === "recommended"))){ -const err99 = {instancePath:instancePath+"/options/" + i3,schemaPath:"#/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data59.label !== undefined){ -if(typeof data59.label !== "string"){ -const err100 = {instancePath:instancePath+"/options/" + i3+"/label",schemaPath:"#/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data59.description !== undefined){ -if(typeof data59.description !== "string"){ -const err101 = {instancePath:instancePath+"/options/" + i3+"/description",schemaPath:"#/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data59.recommended !== undefined){ -if(typeof data59.recommended !== "boolean"){ -const err102 = {instancePath:instancePath+"/options/" + i3+"/recommended",schemaPath:"#/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -} -else { -const err103 = {instancePath:instancePath+"/options/" + i3,schemaPath:"#/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -} -} -if(data.multiple !== undefined){ -if(typeof data.multiple !== "boolean"){ -const err104 = {instancePath:instancePath+"/multiple",schemaPath:"#/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data.questions !== undefined){ -let data64 = data.questions; -if((data64 !== null) && (!(Array.isArray(data64)))){ -const err105 = {instancePath:instancePath+"/questions",schemaPath:"#/properties/questions/type",keyword:"type",params:{type: schema95.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(Array.isArray(data64)){ -const len4 = data64.length; -for(let i4=0; i4<len4; i4++){ -let data65 = data64[i4]; -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.question === undefined){ -const err106 = {instancePath:instancePath+"/questions/" + i4,schemaPath:"#/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -for(const key4 in data65){ -if(!(((key4 === "question") || (key4 === "options")) || (key4 === "multiple"))){ -const err107 = {instancePath:instancePath+"/questions/" + i4,schemaPath:"#/properties/questions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data65.question !== undefined){ -if(typeof data65.question !== "string"){ -const err108 = {instancePath:instancePath+"/questions/" + i4+"/question",schemaPath:"#/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data65.options !== undefined){ -let data67 = data65.options; -if((data67 !== null) && (!(Array.isArray(data67)))){ -const err109 = {instancePath:instancePath+"/questions/" + i4+"/options",schemaPath:"#/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema95.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -if(Array.isArray(data67)){ -const len5 = data67.length; -for(let i5=0; i5<len5; i5++){ -let data68 = data67[i5]; -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -if(data68.label === undefined){ -const err110 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5,schemaPath:"#/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -for(const key5 in data68){ -if(!(((key5 === "label") || (key5 === "description")) || (key5 === "recommended"))){ -const err111 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5,schemaPath:"#/properties/questions/items/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data68.label !== undefined){ -if(typeof data68.label !== "string"){ -const err112 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/label",schemaPath:"#/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data68.description !== undefined){ -if(typeof data68.description !== "string"){ -const err113 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/description",schemaPath:"#/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data68.recommended !== undefined){ -if(typeof data68.recommended !== "boolean"){ -const err114 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/recommended",schemaPath:"#/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -} -else { -const err115 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5,schemaPath:"#/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -} -} -if(data65.multiple !== undefined){ -if(typeof data65.multiple !== "boolean"){ -const err116 = {instancePath:instancePath+"/questions/" + i4+"/multiple",schemaPath:"#/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -} -else { -const err117 = {instancePath:instancePath+"/questions/" + i4,schemaPath:"#/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -} -} -if(data.answer !== undefined){ -let data73 = data.answer; -if((data73 !== null) && (!(Array.isArray(data73)))){ -const err118 = {instancePath:instancePath+"/answer",schemaPath:"#/properties/answer/type",keyword:"type",params:{type: schema95.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(Array.isArray(data73)){ -const len6 = data73.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data73[i6] !== "string"){ -const err119 = {instancePath:instancePath+"/answer/" + i6,schemaPath:"#/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -} -} -if(data.dismissed !== undefined){ -if(typeof data.dismissed !== "boolean"){ -const err120 = {instancePath:instancePath+"/dismissed",schemaPath:"#/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -if(data.answers !== undefined){ -let data76 = data.answers; -if((data76 !== null) && (!(Array.isArray(data76)))){ -const err121 = {instancePath:instancePath+"/answers",schemaPath:"#/properties/answers/type",keyword:"type",params:{type: schema95.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(Array.isArray(data76)){ -const len7 = data76.length; -for(let i7=0; i7<len7; i7++){ -let data77 = data76[i7]; -if(data77 && typeof data77 == "object" && !Array.isArray(data77)){ -for(const key6 in data77){ -if(!((key6 === "answer") || (key6 === "dismissed"))){ -const err122 = {instancePath:instancePath+"/answers/" + i7,schemaPath:"#/properties/answers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data77.answer !== undefined){ -let data78 = data77.answer; -if((data78 !== null) && (!(Array.isArray(data78)))){ -const err123 = {instancePath:instancePath+"/answers/" + i7+"/answer",schemaPath:"#/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema95.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -if(Array.isArray(data78)){ -const len8 = data78.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data78[i8] !== "string"){ -const err124 = {instancePath:instancePath+"/answers/" + i7+"/answer/" + i8,schemaPath:"#/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -} -} -if(data77.dismissed !== undefined){ -if(typeof data77.dismissed !== "boolean"){ -const err125 = {instancePath:instancePath+"/answers/" + i7+"/dismissed",schemaPath:"#/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -} -else { -const err126 = {instancePath:instancePath+"/answers/" + i7,schemaPath:"#/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -} -} -} -else { -const err127 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -validate94.errors = vErrors; -return errors === 0; -} - -export const ListParams = validate95; -const schema96 = {"type":"object","properties":{"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ListParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ListParams","additionalProperties":false}; - -function validate95(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ListParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "limit")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.limit !== undefined){ -let data0 = data.limit; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err1 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate95.errors = vErrors; -return errors === 0; -} - -export const MCPAttachParams = validate96; -const schema97 = {"type":"object","properties":{"servers":{"type":"object","additionalProperties":{"type":"object","properties":{"command":{"type":["null","array"],"items":{"type":"string"}},"env":{"type":"object","additionalProperties":{"type":"string"}},"cwd":{"type":"string"},"url":{"type":"string"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"enabled":{"type":["null","boolean"]},"note":{"type":"string"},"startup_timeout":{"type":"integer"},"tool_timeout":{"type":"integer"},"source":{"type":"string"},"origin":{"type":"string"}},"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/MCPAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPAttachParams","required":["servers"],"additionalProperties":false}; - -function validate96(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPAttachParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.servers === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "servers")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.servers !== undefined){ -let data0 = data.servers; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key1 in data0){ -let data1 = data0[key1]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key2 in data1){ -if(!(func2.call(schema97.properties.servers.additionalProperties.properties, key2))){ -const err2 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data1.command !== undefined){ -let data2 = data1.command; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err3 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/command",schemaPath:"#/properties/servers/additionalProperties/properties/command/type",keyword:"type",params:{type: schema97.properties.servers.additionalProperties.properties.command.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err4 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/command/" + i0,schemaPath:"#/properties/servers/additionalProperties/properties/command/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -if(data1.env !== undefined){ -let data4 = data1.env; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -for(const key3 in data4){ -if(typeof data4[key3] !== "string"){ -const err5 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/env/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/properties/env/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/env",schemaPath:"#/properties/servers/additionalProperties/properties/env/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.cwd !== undefined){ -if(typeof data1.cwd !== "string"){ -const err7 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/cwd",schemaPath:"#/properties/servers/additionalProperties/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.url !== undefined){ -if(typeof data1.url !== "string"){ -const err8 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/url",schemaPath:"#/properties/servers/additionalProperties/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.headers !== undefined){ -let data8 = data1.headers; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -for(const key4 in data8){ -if(typeof data8[key4] !== "string"){ -const err9 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/headers/" + key4.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/properties/headers/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/headers",schemaPath:"#/properties/servers/additionalProperties/properties/headers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.enabled !== undefined){ -let data10 = data1.enabled; -if((data10 !== null) && (typeof data10 !== "boolean")){ -const err11 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/enabled",schemaPath:"#/properties/servers/additionalProperties/properties/enabled/type",keyword:"type",params:{type: schema97.properties.servers.additionalProperties.properties.enabled.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.note !== undefined){ -if(typeof data1.note !== "string"){ -const err12 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/note",schemaPath:"#/properties/servers/additionalProperties/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.startup_timeout !== undefined){ -let data12 = data1.startup_timeout; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err13 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/startup_timeout",schemaPath:"#/properties/servers/additionalProperties/properties/startup_timeout/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.tool_timeout !== undefined){ -let data13 = data1.tool_timeout; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err14 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/tool_timeout",schemaPath:"#/properties/servers/additionalProperties/properties/tool_timeout/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err15 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/source",schemaPath:"#/properties/servers/additionalProperties/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data1.origin !== undefined){ -if(typeof data1.origin !== "string"){ -const err16 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/origin",schemaPath:"#/properties/servers/additionalProperties/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/servers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/servers",schemaPath:"#/properties/servers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -else { -const err19 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -validate96.errors = vErrors; -return errors === 0; -} - -export const MCPBrandIconsParams = validate97; -const schema98 = {"type":"object","properties":{"keys":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPBrandIconsParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPBrandIconsParams","required":["keys"],"additionalProperties":false}; - -function validate97(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPBrandIconsParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.keys === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "keys"},message:"must have required property '"+"keys"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "keys")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.keys !== undefined){ -let data0 = data.keys; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/keys",schemaPath:"#/properties/keys/type",keyword:"type",params:{type: schema98.properties.keys.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err3 = {instancePath:instancePath+"/keys/" + i0,schemaPath:"#/properties/keys/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate97.errors = vErrors; -return errors === 0; -} - -export const MCPBrandIconsResult = validate98; -const schema99 = {"type":"object","properties":{"icons":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPBrandIconsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPBrandIconsResult","required":["icons"],"additionalProperties":false}; - -function validate98(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPBrandIconsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.icons === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "icons"},message:"must have required property '"+"icons"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "icons")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.icons !== undefined){ -let data0 = data.icons; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key1 in data0){ -if(typeof data0[key1] !== "string"){ -const err2 = {instancePath:instancePath+"/icons/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/icons/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath:instancePath+"/icons",schemaPath:"#/properties/icons/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate98.errors = vErrors; -return errors === 0; -} - -export const MCPImportApplyParams = validate99; -const schema100 = {"type":"object","properties":{"cwd":{"type":"string"},"names":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportApplyParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportApplyParams","required":["names"],"additionalProperties":false}; - -function validate99(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportApplyParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.names === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "names"},message:"must have required property '"+"names"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "cwd") || (key0 === "names"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err2 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.names !== undefined){ -let data1 = data.names; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err3 = {instancePath:instancePath+"/names",schemaPath:"#/properties/names/type",keyword:"type",params:{type: schema100.properties.names.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err4 = {instancePath:instancePath+"/names/" + i0,schemaPath:"#/properties/names/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate99.errors = vErrors; -return errors === 0; -} - -export const MCPImportApplyResult = validate100; -const schema101 = {"type":"object","properties":{"imported":{"type":["null","array"],"items":{"type":"string"}},"skipped":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportApplyResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportApplyResult","required":["imported"],"additionalProperties":false}; - -function validate100(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportApplyResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.imported === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "imported"},message:"must have required property '"+"imported"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "imported") || (key0 === "skipped"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.imported !== undefined){ -let data0 = data.imported; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/imported",schemaPath:"#/properties/imported/type",keyword:"type",params:{type: schema101.properties.imported.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err3 = {instancePath:instancePath+"/imported/" + i0,schemaPath:"#/properties/imported/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -if(data.skipped !== undefined){ -let data2 = data.skipped; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -for(const key1 in data2){ -if(typeof data2[key1] !== "string"){ -const err4 = {instancePath:instancePath+"/skipped/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/skipped/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath:instancePath+"/skipped",schemaPath:"#/properties/skipped/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate100.errors = vErrors; -return errors === 0; -} - -export const MCPImportCandidatesParams = validate101; -const schema102 = {"type":"object","properties":{"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MCPImportCandidatesParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportCandidatesParams","additionalProperties":false}; - -function validate101(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportCandidatesParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "cwd")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err1 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate101.errors = vErrors; -return errors === 0; -} - -export const MCPImportCandidatesResult = validate102; -const schema103 = {"type":"object","properties":{"candidates":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"source":{"type":"string"},"state":{"type":"string"},"note":{"type":"string"},"brand_hint":{"type":"string"},"brand_key":{"type":"string"}},"required":["name","source","state"],"additionalProperties":false}},"offered":{"type":"boolean"},"config_path":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportCandidatesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportCandidatesResult","required":["candidates","offered","config_path"],"additionalProperties":false}; - -function validate102(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportCandidatesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.candidates === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "candidates"},message:"must have required property '"+"candidates"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.offered === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered"},message:"must have required property '"+"offered"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.config_path === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "config_path"},message:"must have required property '"+"config_path"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "candidates") || (key0 === "offered")) || (key0 === "config_path")) || (key0 === "errors"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.candidates !== undefined){ -let data0 = data.candidates; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err4 = {instancePath:instancePath+"/candidates",schemaPath:"#/properties/candidates/type",keyword:"type",params:{type: schema103.properties.candidates.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.name === undefined){ -const err5 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.source === undefined){ -const err6 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.state === undefined){ -const err7 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data1){ -if(!((((((key1 === "name") || (key1 === "source")) || (key1 === "state")) || (key1 === "note")) || (key1 === "brand_hint")) || (key1 === "brand_key"))){ -const err8 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err9 = {instancePath:instancePath+"/candidates/" + i0+"/name",schemaPath:"#/properties/candidates/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err10 = {instancePath:instancePath+"/candidates/" + i0+"/source",schemaPath:"#/properties/candidates/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.state !== undefined){ -if(typeof data1.state !== "string"){ -const err11 = {instancePath:instancePath+"/candidates/" + i0+"/state",schemaPath:"#/properties/candidates/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.note !== undefined){ -if(typeof data1.note !== "string"){ -const err12 = {instancePath:instancePath+"/candidates/" + i0+"/note",schemaPath:"#/properties/candidates/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.brand_hint !== undefined){ -if(typeof data1.brand_hint !== "string"){ -const err13 = {instancePath:instancePath+"/candidates/" + i0+"/brand_hint",schemaPath:"#/properties/candidates/items/properties/brand_hint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.brand_key !== undefined){ -if(typeof data1.brand_key !== "string"){ -const err14 = {instancePath:instancePath+"/candidates/" + i0+"/brand_key",schemaPath:"#/properties/candidates/items/properties/brand_key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data.offered !== undefined){ -if(typeof data.offered !== "boolean"){ -const err16 = {instancePath:instancePath+"/offered",schemaPath:"#/properties/offered/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.config_path !== undefined){ -if(typeof data.config_path !== "string"){ -const err17 = {instancePath:instancePath+"/config_path",schemaPath:"#/properties/config_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.errors !== undefined){ -let data10 = data.errors; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -for(const key2 in data10){ -if(typeof data10[key2] !== "string"){ -const err18 = {instancePath:instancePath+"/errors/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/errors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -else { -const err19 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -validate102.errors = vErrors; -return errors === 0; -} - -export const MCPImportParams = validate103; -const schema104 = {"type":"object","properties":{"source":{"type":"string"},"enabled":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MCPImportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportParams","required":["source","enabled"],"additionalProperties":false}; - -function validate103(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.source === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.enabled === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "source") || (key0 === "enabled"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err3 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err4 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate103.errors = vErrors; -return errors === 0; -} - -export const MCPImportStatusResult = validate104; -const schema105 = {"type":"object","properties":{"claude":{"type":"boolean"},"codex":{"type":"boolean"},"project":{"type":"boolean"},"opencode":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MCPImportStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportStatusResult","required":["claude","codex","project","opencode"],"additionalProperties":false}; - -function validate104(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.claude === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "claude"},message:"must have required property '"+"claude"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.codex === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "codex"},message:"must have required property '"+"codex"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.project === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "project"},message:"must have required property '"+"project"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.opencode === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "opencode"},message:"must have required property '"+"opencode"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "claude") || (key0 === "codex")) || (key0 === "project")) || (key0 === "opencode"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.claude !== undefined){ -if(typeof data.claude !== "boolean"){ -const err5 = {instancePath:instancePath+"/claude",schemaPath:"#/properties/claude/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.codex !== undefined){ -if(typeof data.codex !== "boolean"){ -const err6 = {instancePath:instancePath+"/codex",schemaPath:"#/properties/codex/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.project !== undefined){ -if(typeof data.project !== "boolean"){ -const err7 = {instancePath:instancePath+"/project",schemaPath:"#/properties/project/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.opencode !== undefined){ -if(typeof data.opencode !== "boolean"){ -const err8 = {instancePath:instancePath+"/opencode",schemaPath:"#/properties/opencode/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate104.errors = vErrors; -return errors === 0; -} - -export const MCPListResult = validate105; -const schema106 = {"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/MCPListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPListResult"}; - -function validate105(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema106.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.name === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.status === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data0){ -if(!((((((key0 === "name") || (key0 === "status")) || (key0 === "note")) || (key0 === "error")) || (key0 === "tools")) || (key0 === "source"))){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err4 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.status !== undefined){ -if(typeof data0.status !== "string"){ -const err5 = {instancePath:instancePath+"/" + i0+"/status",schemaPath:"#/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.note !== undefined){ -if(typeof data0.note !== "string"){ -const err6 = {instancePath:instancePath+"/" + i0+"/note",schemaPath:"#/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.error !== undefined){ -if(typeof data0.error !== "string"){ -const err7 = {instancePath:instancePath+"/" + i0+"/error",schemaPath:"#/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data5 = data0.tools; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err8 = {instancePath:instancePath+"/" + i0+"/tools",schemaPath:"#/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err9 = {instancePath:instancePath+"/" + i0+"/source",schemaPath:"#/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -validate105.errors = vErrors; -return errors === 0; -} - -export const MCPRefreshResult = validate106; -const schema107 = {"type":"object","properties":{"added":{"type":["null","array"],"items":{"type":"string"}},"existing":{"type":["null","array"],"items":{"type":"string"}},"changed":{"type":["null","array"],"items":{"type":"string"}},"servers":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":false}},"blocked":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":false}},"source_errors":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/MCPRefreshResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPRefreshResult","required":["added","existing","changed","servers","blocked","source_errors"],"additionalProperties":false}; - -function validate106(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPRefreshResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.added === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "added"},message:"must have required property '"+"added"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.existing === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "existing"},message:"must have required property '"+"existing"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.changed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "changed"},message:"must have required property '"+"changed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.servers === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.blocked === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "blocked"},message:"must have required property '"+"blocked"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.source_errors === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "source_errors"},message:"must have required property '"+"source_errors"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "added") || (key0 === "existing")) || (key0 === "changed")) || (key0 === "servers")) || (key0 === "blocked")) || (key0 === "source_errors"))){ -const err6 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.added !== undefined){ -let data0 = data.added; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err7 = {instancePath:instancePath+"/added",schemaPath:"#/properties/added/type",keyword:"type",params:{type: schema107.properties.added.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err8 = {instancePath:instancePath+"/added/" + i0,schemaPath:"#/properties/added/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -if(data.existing !== undefined){ -let data2 = data.existing; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err9 = {instancePath:instancePath+"/existing",schemaPath:"#/properties/existing/type",keyword:"type",params:{type: schema107.properties.existing.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(Array.isArray(data2)){ -const len1 = data2.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data2[i1] !== "string"){ -const err10 = {instancePath:instancePath+"/existing/" + i1,schemaPath:"#/properties/existing/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data.changed !== undefined){ -let data4 = data.changed; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err11 = {instancePath:instancePath+"/changed",schemaPath:"#/properties/changed/type",keyword:"type",params:{type: schema107.properties.changed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(Array.isArray(data4)){ -const len2 = data4.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data4[i2] !== "string"){ -const err12 = {instancePath:instancePath+"/changed/" + i2,schemaPath:"#/properties/changed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.servers !== undefined){ -let data6 = data.servers; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err13 = {instancePath:instancePath+"/servers",schemaPath:"#/properties/servers/type",keyword:"type",params:{type: schema107.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(Array.isArray(data6)){ -const len3 = data6.length; -for(let i3=0; i3<len3; i3++){ -let data7 = data6[i3]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.name === undefined){ -const err14 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.status === undefined){ -const err15 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -for(const key1 in data7){ -if(!((((((key1 === "name") || (key1 === "status")) || (key1 === "note")) || (key1 === "error")) || (key1 === "tools")) || (key1 === "source"))){ -const err16 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data7.name !== undefined){ -if(typeof data7.name !== "string"){ -const err17 = {instancePath:instancePath+"/servers/" + i3+"/name",schemaPath:"#/properties/servers/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data7.status !== undefined){ -if(typeof data7.status !== "string"){ -const err18 = {instancePath:instancePath+"/servers/" + i3+"/status",schemaPath:"#/properties/servers/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data7.note !== undefined){ -if(typeof data7.note !== "string"){ -const err19 = {instancePath:instancePath+"/servers/" + i3+"/note",schemaPath:"#/properties/servers/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data7.error !== undefined){ -if(typeof data7.error !== "string"){ -const err20 = {instancePath:instancePath+"/servers/" + i3+"/error",schemaPath:"#/properties/servers/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data7.tools !== undefined){ -let data12 = data7.tools; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err21 = {instancePath:instancePath+"/servers/" + i3+"/tools",schemaPath:"#/properties/servers/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.source !== undefined){ -if(typeof data7.source !== "string"){ -const err22 = {instancePath:instancePath+"/servers/" + i3+"/source",schemaPath:"#/properties/servers/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data.blocked !== undefined){ -let data14 = data.blocked; -if((data14 !== null) && (!(Array.isArray(data14)))){ -const err24 = {instancePath:instancePath+"/blocked",schemaPath:"#/properties/blocked/type",keyword:"type",params:{type: schema107.properties.blocked.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data14)){ -const len4 = data14.length; -for(let i4=0; i4<len4; i4++){ -let data15 = data14[i4]; -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.name === undefined){ -const err25 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data15.status === undefined){ -const err26 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -for(const key2 in data15){ -if(!((((((key2 === "name") || (key2 === "status")) || (key2 === "note")) || (key2 === "error")) || (key2 === "tools")) || (key2 === "source"))){ -const err27 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data15.name !== undefined){ -if(typeof data15.name !== "string"){ -const err28 = {instancePath:instancePath+"/blocked/" + i4+"/name",schemaPath:"#/properties/blocked/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data15.status !== undefined){ -if(typeof data15.status !== "string"){ -const err29 = {instancePath:instancePath+"/blocked/" + i4+"/status",schemaPath:"#/properties/blocked/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data15.note !== undefined){ -if(typeof data15.note !== "string"){ -const err30 = {instancePath:instancePath+"/blocked/" + i4+"/note",schemaPath:"#/properties/blocked/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data15.error !== undefined){ -if(typeof data15.error !== "string"){ -const err31 = {instancePath:instancePath+"/blocked/" + i4+"/error",schemaPath:"#/properties/blocked/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data15.tools !== undefined){ -let data20 = data15.tools; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err32 = {instancePath:instancePath+"/blocked/" + i4+"/tools",schemaPath:"#/properties/blocked/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data15.source !== undefined){ -if(typeof data15.source !== "string"){ -const err33 = {instancePath:instancePath+"/blocked/" + i4+"/source",schemaPath:"#/properties/blocked/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -else { -const err34 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -} -if(data.source_errors !== undefined){ -let data22 = data.source_errors; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err35 = {instancePath:instancePath+"/source_errors",schemaPath:"#/properties/source_errors/type",keyword:"type",params:{type: schema107.properties.source_errors.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(Array.isArray(data22)){ -const len5 = data22.length; -for(let i5=0; i5<len5; i5++){ -let data23 = data22[i5]; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.name === undefined){ -const err36 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data23.status === undefined){ -const err37 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -for(const key3 in data23){ -if(!((((((key3 === "name") || (key3 === "status")) || (key3 === "note")) || (key3 === "error")) || (key3 === "tools")) || (key3 === "source"))){ -const err38 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data23.name !== undefined){ -if(typeof data23.name !== "string"){ -const err39 = {instancePath:instancePath+"/source_errors/" + i5+"/name",schemaPath:"#/properties/source_errors/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data23.status !== undefined){ -if(typeof data23.status !== "string"){ -const err40 = {instancePath:instancePath+"/source_errors/" + i5+"/status",schemaPath:"#/properties/source_errors/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data23.note !== undefined){ -if(typeof data23.note !== "string"){ -const err41 = {instancePath:instancePath+"/source_errors/" + i5+"/note",schemaPath:"#/properties/source_errors/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data23.error !== undefined){ -if(typeof data23.error !== "string"){ -const err42 = {instancePath:instancePath+"/source_errors/" + i5+"/error",schemaPath:"#/properties/source_errors/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data23.tools !== undefined){ -let data28 = data23.tools; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err43 = {instancePath:instancePath+"/source_errors/" + i5+"/tools",schemaPath:"#/properties/source_errors/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data23.source !== undefined){ -if(typeof data23.source !== "string"){ -const err44 = {instancePath:instancePath+"/source_errors/" + i5+"/source",schemaPath:"#/properties/source_errors/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -else { -const err45 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -} -} -else { -const err46 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -validate106.errors = vErrors; -return errors === 0; -} - -export const MCPServerParams = validate107; -const schema108 = {"type":"object","properties":{"name":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MCPServerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPServerParams","required":["name"],"additionalProperties":false}; - -function validate107(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPServerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.name === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "name")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err2 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate107.errors = vErrors; -return errors === 0; -} - -export const MailboxInspection = validate108; -const schema109 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"sender":{"type":"string"},"recipient":{"type":"string"},"kind":{"type":"string"},"delivery":{"type":"string"},"subject":{"type":"string"},"excerpt":{"type":"string"},"body":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"evidence_handle":{"type":"string"},"status":{"type":"string"},"available_at":{"type":"string"},"created_at":{"type":"string"},"delivered_at":{"type":"string"},"delivered_turn_id":{"type":"string"},"done_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MailboxInspection","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxInspection","required":["id","revision","sender","recipient","kind","delivery","subject","excerpt","body","status","available_at","created_at","delivered_at","done_at"],"additionalProperties":false}; - -function validate108(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxInspection" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.sender === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "sender"},message:"must have required property '"+"sender"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.recipient === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "recipient"},message:"must have required property '"+"recipient"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.kind === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.delivery === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "delivery"},message:"must have required property '"+"delivery"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.subject === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subject"},message:"must have required property '"+"subject"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.excerpt === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "excerpt"},message:"must have required property '"+"excerpt"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.body === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.status === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.available_at === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "available_at"},message:"must have required property '"+"available_at"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.created_at === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.delivered_at === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "delivered_at"},message:"must have required property '"+"delivered_at"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.done_at === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "done_at"},message:"must have required property '"+"done_at"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema109.properties, key0))){ -const err14 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err15 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.revision !== undefined){ -let data1 = data.revision; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err16 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err17 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -else { -const err18 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.sender !== undefined){ -if(typeof data.sender !== "string"){ -const err19 = {instancePath:instancePath+"/sender",schemaPath:"#/properties/sender/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.recipient !== undefined){ -if(typeof data.recipient !== "string"){ -const err20 = {instancePath:instancePath+"/recipient",schemaPath:"#/properties/recipient/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err21 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err22 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.subject !== undefined){ -if(typeof data.subject !== "string"){ -const err23 = {instancePath:instancePath+"/subject",schemaPath:"#/properties/subject/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.excerpt !== undefined){ -if(typeof data.excerpt !== "string"){ -const err24 = {instancePath:instancePath+"/excerpt",schemaPath:"#/properties/excerpt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.body !== undefined){ -let data8 = data.body; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.reference_id === undefined){ -const err25 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data8.digest === undefined){ -const err26 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data8.size === undefined){ -const err27 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data8.media_type === undefined){ -const err28 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data8.source === undefined){ -const err29 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -for(const key1 in data8){ -if(!((((((((key1 === "inline") || (key1 === "text")) || (key1 === "binary")) || (key1 === "reference_id")) || (key1 === "digest")) || (key1 === "size")) || (key1 === "media_type")) || (key1 === "source"))){ -const err30 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data8.text !== undefined){ -let data9 = data8.text; -if((data9 !== null) && (typeof data9 !== "string")){ -const err31 = {instancePath:instancePath+"/body/text",schemaPath:"#/properties/body/properties/text/type",keyword:"type",params:{type: schema109.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data8.binary !== undefined){ -let data10 = data8.binary; -if((typeof data10 !== "string") && (data10 !== null)){ -const err32 = {instancePath:instancePath+"/body/binary",schemaPath:"#/properties/body/properties/binary/type",keyword:"type",params:{type: schema109.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data8.reference_id !== undefined){ -if(typeof data8.reference_id !== "string"){ -const err33 = {instancePath:instancePath+"/body/reference_id",schemaPath:"#/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data8.digest !== undefined){ -if(typeof data8.digest !== "string"){ -const err34 = {instancePath:instancePath+"/body/digest",schemaPath:"#/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data8.size !== undefined){ -let data13 = data8.size; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err35 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err36 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -else { -const err37 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data8.media_type !== undefined){ -if(typeof data8.media_type !== "string"){ -const err38 = {instancePath:instancePath+"/body/media_type",schemaPath:"#/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data8.source !== undefined){ -if(typeof data8.source !== "string"){ -const err39 = {instancePath:instancePath+"/body/source",schemaPath:"#/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -} -else { -const err40 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data.evidence_handle !== undefined){ -if(typeof data.evidence_handle !== "string"){ -const err41 = {instancePath:instancePath+"/evidence_handle",schemaPath:"#/properties/evidence_handle/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err42 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data.available_at !== undefined){ -if(typeof data.available_at !== "string"){ -const err43 = {instancePath:instancePath+"/available_at",schemaPath:"#/properties/available_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err44 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.delivered_at !== undefined){ -if(typeof data.delivered_at !== "string"){ -const err45 = {instancePath:instancePath+"/delivered_at",schemaPath:"#/properties/delivered_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data.delivered_turn_id !== undefined){ -if(typeof data.delivered_turn_id !== "string"){ -const err46 = {instancePath:instancePath+"/delivered_turn_id",schemaPath:"#/properties/delivered_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data.done_at !== undefined){ -if(typeof data.done_at !== "string"){ -const err47 = {instancePath:instancePath+"/done_at",schemaPath:"#/properties/done_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -else { -const err48 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -validate108.errors = vErrors; -return errors === 0; -} - -export const MailboxPage = validate109; -const schema110 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"sender":{"type":"string"},"recipient":{"type":"string"},"kind":{"type":"string"},"delivery":{"type":"string"},"subject":{"type":"string"},"excerpt":{"type":"string"},"body":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"evidence_handle":{"type":"string"},"status":{"type":"string"},"available_at":{"type":"string"},"created_at":{"type":"string"},"delivered_at":{"type":"string"},"delivered_turn_id":{"type":"string"},"done_at":{"type":"string"}},"required":["id","revision","sender","recipient","kind","delivery","subject","excerpt","body","status","available_at","created_at","delivered_at","done_at"],"additionalProperties":false}},"next_cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","status","revision","offset"],"additionalProperties":false},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MailboxPage","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxPage","required":["revision","items","has_more"],"additionalProperties":false}; - -function validate109(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.has_more === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "revision") || (key0 === "items")) || (key0 === "next_cursor")) || (key0 === "has_more"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.items !== undefined){ -let data1 = data.items; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err7 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema110.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.revision === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.sender === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "sender"},message:"must have required property '"+"sender"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.recipient === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "recipient"},message:"must have required property '"+"recipient"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.kind === undefined){ -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.delivery === undefined){ -const err13 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "delivery"},message:"must have required property '"+"delivery"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.subject === undefined){ -const err14 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "subject"},message:"must have required property '"+"subject"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.excerpt === undefined){ -const err15 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "excerpt"},message:"must have required property '"+"excerpt"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.body === undefined){ -const err16 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.status === undefined){ -const err17 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data2.available_at === undefined){ -const err18 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "available_at"},message:"must have required property '"+"available_at"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2.created_at === undefined){ -const err19 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2.delivered_at === undefined){ -const err20 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "delivered_at"},message:"must have required property '"+"delivered_at"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.done_at === undefined){ -const err21 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "done_at"},message:"must have required property '"+"done_at"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -for(const key1 in data2){ -if(!(func2.call(schema110.properties.items.items.properties, key1))){ -const err22 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.revision !== undefined){ -let data4 = data2.revision; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.sender !== undefined){ -if(typeof data2.sender !== "string"){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/sender",schemaPath:"#/properties/items/items/properties/sender/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.recipient !== undefined){ -if(typeof data2.recipient !== "string"){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/recipient",schemaPath:"#/properties/items/items/properties/recipient/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/kind",schemaPath:"#/properties/items/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data2.delivery !== undefined){ -if(typeof data2.delivery !== "string"){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/delivery",schemaPath:"#/properties/items/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data2.subject !== undefined){ -if(typeof data2.subject !== "string"){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/subject",schemaPath:"#/properties/items/items/properties/subject/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data2.excerpt !== undefined){ -if(typeof data2.excerpt !== "string"){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/excerpt",schemaPath:"#/properties/items/items/properties/excerpt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data2.body !== undefined){ -let data11 = data2.body; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.reference_id === undefined){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data11.digest === undefined){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data11.size === undefined){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data11.media_type === undefined){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data11.source === undefined){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -for(const key2 in data11){ -if(!((((((((key2 === "inline") || (key2 === "text")) || (key2 === "binary")) || (key2 === "reference_id")) || (key2 === "digest")) || (key2 === "size")) || (key2 === "media_type")) || (key2 === "source"))){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data11.text !== undefined){ -let data12 = data11.text; -if((data12 !== null) && (typeof data12 !== "string")){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/properties/body/properties/text/type",keyword:"type",params:{type: schema110.properties.items.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data11.binary !== undefined){ -let data13 = data11.binary; -if((typeof data13 !== "string") && (data13 !== null)){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema110.properties.items.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data11.reference_id !== undefined){ -if(typeof data11.reference_id !== "string"){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data11.digest !== undefined){ -if(typeof data11.digest !== "string"){ -const err42 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data11.size !== undefined){ -let data16 = data11.size; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data11.media_type !== undefined){ -if(typeof data11.media_type !== "string"){ -const err46 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data11.source !== undefined){ -if(typeof data11.source !== "string"){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -else { -const err48 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data2.evidence_handle !== undefined){ -if(typeof data2.evidence_handle !== "string"){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/evidence_handle",schemaPath:"#/properties/items/items/properties/evidence_handle/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/status",schemaPath:"#/properties/items/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data2.available_at !== undefined){ -if(typeof data2.available_at !== "string"){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/available_at",schemaPath:"#/properties/items/items/properties/available_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data2.created_at !== undefined){ -if(typeof data2.created_at !== "string"){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/created_at",schemaPath:"#/properties/items/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data2.delivered_at !== undefined){ -if(typeof data2.delivered_at !== "string"){ -const err53 = {instancePath:instancePath+"/items/" + i0+"/delivered_at",schemaPath:"#/properties/items/items/properties/delivered_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data2.delivered_turn_id !== undefined){ -if(typeof data2.delivered_turn_id !== "string"){ -const err54 = {instancePath:instancePath+"/items/" + i0+"/delivered_turn_id",schemaPath:"#/properties/items/items/properties/delivered_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data2.done_at !== undefined){ -if(typeof data2.done_at !== "string"){ -const err55 = {instancePath:instancePath+"/items/" + i0+"/done_at",schemaPath:"#/properties/items/items/properties/done_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -} -else { -const err56 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -} -} -if(data.next_cursor !== undefined){ -let data26 = data.next_cursor; -if((data26 !== null) && (!(data26 && typeof data26 == "object" && !Array.isArray(data26)))){ -const err57 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema110.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.root_id === undefined){ -const err58 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data26.agent_id === undefined){ -const err59 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data26.status === undefined){ -const err60 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data26.revision === undefined){ -const err61 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data26.offset === undefined){ -const err62 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -for(const key3 in data26){ -if(!(((((key3 === "root_id") || (key3 === "agent_id")) || (key3 === "status")) || (key3 === "revision")) || (key3 === "offset"))){ -const err63 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data26.root_id !== undefined){ -if(typeof data26.root_id !== "string"){ -const err64 = {instancePath:instancePath+"/next_cursor/root_id",schemaPath:"#/properties/next_cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data26.agent_id !== undefined){ -if(typeof data26.agent_id !== "string"){ -const err65 = {instancePath:instancePath+"/next_cursor/agent_id",schemaPath:"#/properties/next_cursor/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data26.status !== undefined){ -if(typeof data26.status !== "string"){ -const err66 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data26.revision !== undefined){ -let data30 = data26.revision; -if(typeof data30 === "string"){ -if(!pattern0.test(data30)){ -const err67 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(!(formats0.validate(data30))){ -const err68 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -else { -const err69 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data26.offset !== undefined){ -let data31 = data26.offset; -if(typeof data31 === "string"){ -if(!pattern0.test(data31)){ -const err70 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(!(formats0.validate(data31))){ -const err71 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -else { -const err72 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err73 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -} -else { -const err74 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -validate109.errors = vErrors; -return errors === 0; -} - -export const MailboxPageParams = validate110; -const schema111 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","status","revision","offset"],"additionalProperties":false},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/MailboxPageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxPageParams","required":["root_id","agent_id","limit","max_bytes"],"additionalProperties":false}; - -function validate110(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxPageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.max_bytes === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "root_id") || (key0 === "agent_id")) || (key0 === "status")) || (key0 === "cursor")) || (key0 === "limit")) || (key0 === "max_bytes"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err6 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err7 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data3 = data.cursor; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema111.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.root_id === undefined){ -const err9 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data3.agent_id === undefined){ -const err10 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data3.status === undefined){ -const err11 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data3.revision === undefined){ -const err12 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data3.offset === undefined){ -const err13 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key1 in data3){ -if(!(((((key1 === "root_id") || (key1 === "agent_id")) || (key1 === "status")) || (key1 === "revision")) || (key1 === "offset"))){ -const err14 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data3.root_id !== undefined){ -if(typeof data3.root_id !== "string"){ -const err15 = {instancePath:instancePath+"/cursor/root_id",schemaPath:"#/properties/cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data3.agent_id !== undefined){ -if(typeof data3.agent_id !== "string"){ -const err16 = {instancePath:instancePath+"/cursor/agent_id",schemaPath:"#/properties/cursor/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data3.status !== undefined){ -if(typeof data3.status !== "string"){ -const err17 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data3.revision !== undefined){ -let data7 = data3.revision; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err18 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err19 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -else { -const err20 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data3.offset !== undefined){ -let data8 = data3.offset; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err21 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err22 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data9 = data.limit; -if(!((typeof data9 == "number") && (!(data9 % 1) && !isNaN(data9)))){ -const err24 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data10 = data.max_bytes; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err25 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -else { -const err26 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -validate110.errors = vErrors; -return errors === 0; -} - -export const MailboxReadParams = validate111; -const schema112 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MailboxReadParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxReadParams","required":["root_id","agent_id","id"],"additionalProperties":false}; - -function validate111(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxReadParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "root_id") || (key0 === "agent_id")) || (key0 === "id"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err5 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err6 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate111.errors = vErrors; -return errors === 0; -} - -export const ModelParams = validate112; -const schema113 = {"type":"object","properties":{"effort":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"persist_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ModelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ModelParams","required":["model","persist_default"],"additionalProperties":false}; - -function validate112(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ModelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.persist_default === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "persist_default"},message:"must have required property '"+"persist_default"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "effort") || (key0 === "model")) || (key0 === "provider")) || (key0 === "persist_default"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err3 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err4 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err5 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.persist_default !== undefined){ -if(typeof data.persist_default !== "boolean"){ -const err6 = {instancePath:instancePath+"/persist_default",schemaPath:"#/properties/persist_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate112.errors = vErrors; -return errors === 0; -} - -export const ModelResult = validate113; -const schema114 = {"type":"object","properties":{"reload_pending":{"type":"boolean"},"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ModelResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ModelResult","required":["model","provider"],"additionalProperties":false}; - -function validate113(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ModelResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "reload_pending") || (key0 === "model")) || (key0 === "provider"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.reload_pending !== undefined){ -if(typeof data.reload_pending !== "boolean"){ -const err3 = {instancePath:instancePath+"/reload_pending",schemaPath:"#/properties/reload_pending/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err4 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err5 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate113.errors = vErrors; -return errors === 0; -} - -export const PathParams = validate114; -const schema115 = {"type":"object","properties":{"path":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PathParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PathParams","required":["path"],"additionalProperties":false}; - -function validate114(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PathParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "path")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err2 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate114.errors = vErrors; -return errors === 0; -} - -export const PathResult = validate115; -const schema116 = {"type":"object","properties":{"path":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PathResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PathResult","required":["path"],"additionalProperties":false}; - -function validate115(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PathResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "path")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err2 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate115.errors = vErrors; -return errors === 0; -} - -export const PermissionConfigureParams = validate116; -const schema117 = {"type":"object","properties":{"external_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/PermissionConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionConfigureParams","required":["external_permissions"],"additionalProperties":false}; - -function validate116(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.external_permissions === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "external_permissions"},message:"must have required property '"+"external_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "external_permissions")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.external_permissions !== undefined){ -if(typeof data.external_permissions !== "boolean"){ -const err2 = {instancePath:instancePath+"/external_permissions",schemaPath:"#/properties/external_permissions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate116.errors = vErrors; -return errors === 0; -} - -export const PermissionDecision = validate117; -const schema118 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"permission_id":{"type":"string"},"allow":{"type":"boolean"},"reason":{"type":"string"},"remember":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PermissionDecision","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecision","required":["command_id","root_id","permission_id","allow"],"additionalProperties":false}; - -function validate117(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecision" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.permission_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permission_id"},message:"must have required property '"+"permission_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.allow === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "allow"},message:"must have required property '"+"allow"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "command_id") || (key0 === "root_id")) || (key0 === "permission_id")) || (key0 === "allow")) || (key0 === "reason")) || (key0 === "remember"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err5 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.permission_id !== undefined){ -if(typeof data.permission_id !== "string"){ -const err7 = {instancePath:instancePath+"/permission_id",schemaPath:"#/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.allow !== undefined){ -if(typeof data.allow !== "boolean"){ -const err8 = {instancePath:instancePath+"/allow",schemaPath:"#/properties/allow/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err9 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.remember !== undefined){ -if(typeof data.remember !== "string"){ -const err10 = {instancePath:instancePath+"/remember",schemaPath:"#/properties/remember/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate117.errors = vErrors; -return errors === 0; -} - -export const PermissionDecisionParams = validate118; -const schema119 = {"type":"object","properties":{"decision":{"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"permission_id":{"type":"string"},"allow":{"type":"boolean"},"reason":{"type":"string"},"remember":{"type":"string"}},"required":["command_id","root_id","permission_id","allow"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/PermissionDecisionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecisionParams","required":["decision"],"additionalProperties":false}; - -function validate118(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecisionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.decision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "decision"},message:"must have required property '"+"decision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "decision")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.decision !== undefined){ -let data0 = data.decision; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.command_id === undefined){ -const err2 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.root_id === undefined){ -const err3 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.permission_id === undefined){ -const err4 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "permission_id"},message:"must have required property '"+"permission_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.allow === undefined){ -const err5 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "allow"},message:"must have required property '"+"allow"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key1 in data0){ -if(!((((((key1 === "command_id") || (key1 === "root_id")) || (key1 === "permission_id")) || (key1 === "allow")) || (key1 === "reason")) || (key1 === "remember"))){ -const err6 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.command_id !== undefined){ -if(typeof data0.command_id !== "string"){ -const err7 = {instancePath:instancePath+"/decision/command_id",schemaPath:"#/properties/decision/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err8 = {instancePath:instancePath+"/decision/root_id",schemaPath:"#/properties/decision/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.permission_id !== undefined){ -if(typeof data0.permission_id !== "string"){ -const err9 = {instancePath:instancePath+"/decision/permission_id",schemaPath:"#/properties/decision/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.allow !== undefined){ -if(typeof data0.allow !== "boolean"){ -const err10 = {instancePath:instancePath+"/decision/allow",schemaPath:"#/properties/decision/properties/allow/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.reason !== undefined){ -if(typeof data0.reason !== "string"){ -const err11 = {instancePath:instancePath+"/decision/reason",schemaPath:"#/properties/decision/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data0.remember !== undefined){ -if(typeof data0.remember !== "string"){ -const err12 = {instancePath:instancePath+"/decision/remember",schemaPath:"#/properties/decision/properties/remember/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -validate118.errors = vErrors; -return errors === 0; -} - -export const PermissionDecisionResult = validate119; -const schema120 = {"type":"object","properties":{"operation_id":{"type":"string"},"lease_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PermissionDecisionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecisionResult","required":["operation_id","lease_id"],"additionalProperties":false}; - -function validate119(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecisionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.lease_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "lease_id"},message:"must have required property '"+"lease_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "operation_id") || (key0 === "lease_id"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err3 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.lease_id !== undefined){ -if(typeof data.lease_id !== "string"){ -const err4 = {instancePath:instancePath+"/lease_id",schemaPath:"#/properties/lease_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate119.errors = vErrors; -return errors === 0; -} - -export const PermissionRulesResult = validate120; -const schema121 = {"type":"object","properties":{"rules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"operation":{"type":"string"},"rule":{"type":"string"},"principal_id":{"type":"string"},"created_at":{"type":"string"}},"required":["id","root_id","operation","rule","principal_id","created_at"],"additionalProperties":false}},"global":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/PermissionRulesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionRulesResult","required":["rules","global"],"additionalProperties":false}; - -function validate120(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionRulesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.rules === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.global === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "global"},message:"must have required property '"+"global"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "rules") || (key0 === "global"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.rules !== undefined){ -let data0 = data.rules; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/rules",schemaPath:"#/properties/rules/type",keyword:"type",params:{type: schema121.properties.rules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err4 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.root_id === undefined){ -const err5 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.operation === undefined){ -const err6 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.rule === undefined){ -const err7 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.principal_id === undefined){ -const err8 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "principal_id"},message:"must have required property '"+"principal_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.created_at === undefined){ -const err9 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key1 in data1){ -if(!((((((key1 === "id") || (key1 === "root_id")) || (key1 === "operation")) || (key1 === "rule")) || (key1 === "principal_id")) || (key1 === "created_at"))){ -const err10 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err11 = {instancePath:instancePath+"/rules/" + i0+"/id",schemaPath:"#/properties/rules/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err12 = {instancePath:instancePath+"/rules/" + i0+"/root_id",schemaPath:"#/properties/rules/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.operation !== undefined){ -if(typeof data1.operation !== "string"){ -const err13 = {instancePath:instancePath+"/rules/" + i0+"/operation",schemaPath:"#/properties/rules/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.rule !== undefined){ -if(typeof data1.rule !== "string"){ -const err14 = {instancePath:instancePath+"/rules/" + i0+"/rule",schemaPath:"#/properties/rules/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.principal_id !== undefined){ -if(typeof data1.principal_id !== "string"){ -const err15 = {instancePath:instancePath+"/rules/" + i0+"/principal_id",schemaPath:"#/properties/rules/items/properties/principal_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data1.created_at !== undefined){ -if(typeof data1.created_at !== "string"){ -const err16 = {instancePath:instancePath+"/rules/" + i0+"/created_at",schemaPath:"#/properties/rules/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.global !== undefined){ -let data8 = data.global; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err18 = {instancePath:instancePath+"/global",schemaPath:"#/properties/global/type",keyword:"type",params:{type: schema121.properties.global.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err19 = {instancePath:instancePath+"/global/" + i1,schemaPath:"#/properties/global/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -} -} -else { -const err20 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -validate120.errors = vErrors; -return errors === 0; -} - -export const PingResult = validate121; -const schema122 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"build_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PingResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PingResult","required":["generation","build_id"],"additionalProperties":false}; - -function validate121(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PingResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.build_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "generation") || (key0 === "build_id"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err6 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate121.errors = vErrors; -return errors === 0; -} - -export const ProviderCatalogParams = validate122; -const schema123 = {"type":"object","properties":{"refresh":{"type":"boolean"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderCatalogParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCatalogParams","additionalProperties":false}; - -function validate122(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCatalogParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((key0 === "refresh") || (key0 === "provider"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.refresh !== undefined){ -if(typeof data.refresh !== "boolean"){ -const err1 = {instancePath:instancePath+"/refresh",schemaPath:"#/properties/refresh/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate122.errors = vErrors; -return errors === 0; -} - -export const ProviderCatalogsResult = validate123; -const schema124 = {"type":"object","properties":{"models":{"type":"object","additionalProperties":{"type":"object","properties":{"name":{"type":"string"},"id":{"type":"string"},"providers":{"type":["null","array"],"items":{"type":"string"}},"context":{"type":"integer"},"vision":{"type":"boolean"}},"required":["providers"],"additionalProperties":false}},"providers":{"type":"object","additionalProperties":{"type":"object","properties":{"base_url":{"type":"string"},"available":{"type":["null","boolean"]}},"required":["base_url"],"additionalProperties":false}},"catalogs":{"type":"object","additionalProperties":{"type":"object","properties":{"fetched_at":{"type":"string"},"base_url":{"type":"string"},"models":{"type":["null","array"],"items":{"type":"object","properties":{"pricing":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"completion":{"type":"string"},"input_cache_read":{"type":"string"}},"required":["prompt","completion"],"additionalProperties":false},"pricing_known":{"type":"boolean"},"cache_read_price_known":{"type":"boolean"},"id":{"type":"string"},"context_length":{"type":"integer"},"max_completion_tokens":{"type":"integer"},"reasoning_efforts":{"type":["null","array"],"items":{"type":"string"}},"in_price":{"type":"number"},"out_price":{"type":"number"},"cache_read_price":{"type":"number"},"input_modalities":{"type":["null","array"],"items":{"type":"string"}}},"required":["id"],"additionalProperties":false}}},"required":["fetched_at","base_url","models"],"additionalProperties":false}},"errors":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ProviderCatalogsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCatalogsResult","required":["models","providers","catalogs"],"additionalProperties":false}; - -function validate123(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCatalogsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.models === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.providers === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.catalogs === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "catalogs"},message:"must have required property '"+"catalogs"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "models") || (key0 === "providers")) || (key0 === "catalogs")) || (key0 === "errors"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.models !== undefined){ -let data0 = data.models; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key1 in data0){ -let data1 = data0[key1]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.providers === undefined){ -const err4 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/models/additionalProperties/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key2 in data1){ -if(!(((((key2 === "name") || (key2 === "id")) || (key2 === "providers")) || (key2 === "context")) || (key2 === "vision"))){ -const err5 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/models/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err6 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/name",schemaPath:"#/properties/models/additionalProperties/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err7 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/id",schemaPath:"#/properties/models/additionalProperties/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.providers !== undefined){ -let data4 = data1.providers; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err8 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/providers",schemaPath:"#/properties/models/additionalProperties/properties/providers/type",keyword:"type",params:{type: schema124.properties.models.additionalProperties.properties.providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err9 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/providers/" + i0,schemaPath:"#/properties/models/additionalProperties/properties/providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data1.context !== undefined){ -let data6 = data1.context; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err10 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/context",schemaPath:"#/properties/models/additionalProperties/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.vision !== undefined){ -if(typeof data1.vision !== "boolean"){ -const err11 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/vision",schemaPath:"#/properties/models/additionalProperties/properties/vision/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/models/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/models/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.providers !== undefined){ -let data8 = data.providers; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -for(const key3 in data8){ -let data9 = data8[key3]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.base_url === undefined){ -const err14 = {instancePath:instancePath+"/providers/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/providers/additionalProperties/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -for(const key4 in data9){ -if(!((key4 === "base_url") || (key4 === "available"))){ -const err15 = {instancePath:instancePath+"/providers/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/providers/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data9.base_url !== undefined){ -if(typeof data9.base_url !== "string"){ -const err16 = {instancePath:instancePath+"/providers/" + key3.replace(/~/g, "~0").replace(/\//g, "~1")+"/base_url",schemaPath:"#/properties/providers/additionalProperties/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data9.available !== undefined){ -let data11 = data9.available; -if((data11 !== null) && (typeof data11 !== "boolean")){ -const err17 = {instancePath:instancePath+"/providers/" + key3.replace(/~/g, "~0").replace(/\//g, "~1")+"/available",schemaPath:"#/properties/providers/additionalProperties/properties/available/type",keyword:"type",params:{type: schema124.properties.providers.additionalProperties.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/providers/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/providers/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -else { -const err19 = {instancePath:instancePath+"/providers",schemaPath:"#/properties/providers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.catalogs !== undefined){ -let data12 = data.catalogs; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -for(const key5 in data12){ -let data13 = data12[key5]; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.fetched_at === undefined){ -const err20 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "fetched_at"},message:"must have required property '"+"fetched_at"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data13.base_url === undefined){ -const err21 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data13.models === undefined){ -const err22 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -for(const key6 in data13){ -if(!(((key6 === "fetched_at") || (key6 === "base_url")) || (key6 === "models"))){ -const err23 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data13.fetched_at !== undefined){ -if(typeof data13.fetched_at !== "string"){ -const err24 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/fetched_at",schemaPath:"#/properties/catalogs/additionalProperties/properties/fetched_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data13.base_url !== undefined){ -if(typeof data13.base_url !== "string"){ -const err25 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/base_url",schemaPath:"#/properties/catalogs/additionalProperties/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data13.models !== undefined){ -let data16 = data13.models; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err26 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data16)){ -const len1 = data16.length; -for(let i1=0; i1<len1; i1++){ -let data17 = data16[i1]; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.id === undefined){ -const err27 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -for(const key7 in data17){ -if(!(func2.call(schema124.properties.catalogs.additionalProperties.properties.models.items.properties, key7))){ -const err28 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data17.pricing !== undefined){ -let data18 = data17.pricing; -if((data18 !== null) && (!(data18 && typeof data18 == "object" && !Array.isArray(data18)))){ -const err29 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.pricing.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -if(data18.prompt === undefined){ -const err30 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data18.completion === undefined){ -const err31 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "completion"},message:"must have required property '"+"completion"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -for(const key8 in data18){ -if(!(((key8 === "prompt") || (key8 === "completion")) || (key8 === "input_cache_read"))){ -const err32 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data18.prompt !== undefined){ -if(typeof data18.prompt !== "string"){ -const err33 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/prompt",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data18.completion !== undefined){ -if(typeof data18.completion !== "string"){ -const err34 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/completion",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/completion/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data18.input_cache_read !== undefined){ -if(typeof data18.input_cache_read !== "string"){ -const err35 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/input_cache_read",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/input_cache_read/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -} -if(data17.pricing_known !== undefined){ -if(typeof data17.pricing_known !== "boolean"){ -const err36 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing_known",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing_known/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data17.cache_read_price_known !== undefined){ -if(typeof data17.cache_read_price_known !== "boolean"){ -const err37 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/cache_read_price_known",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/cache_read_price_known/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data17.id !== undefined){ -if(typeof data17.id !== "string"){ -const err38 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/id",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data17.context_length !== undefined){ -let data25 = data17.context_length; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err39 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/context_length",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/context_length/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data17.max_completion_tokens !== undefined){ -let data26 = data17.max_completion_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err40 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/max_completion_tokens",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/max_completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data17.reasoning_efforts !== undefined){ -let data27 = data17.reasoning_efforts; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err41 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/reasoning_efforts",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/reasoning_efforts/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.reasoning_efforts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err42 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/reasoning_efforts/" + i2,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/reasoning_efforts/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -} -if(data17.in_price !== undefined){ -if(!(typeof data17.in_price == "number")){ -const err43 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/in_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/in_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data17.out_price !== undefined){ -if(!(typeof data17.out_price == "number")){ -const err44 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/out_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/out_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.cache_read_price !== undefined){ -if(!(typeof data17.cache_read_price == "number")){ -const err45 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/cache_read_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/cache_read_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.input_modalities !== undefined){ -let data32 = data17.input_modalities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err46 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/input_modalities",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/input_modalities/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.input_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(Array.isArray(data32)){ -const len3 = data32.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data32[i3] !== "string"){ -const err47 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/input_modalities/" + i3,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/input_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -} -} -else { -const err48 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -} -} -} -else { -const err49 = {instancePath:instancePath+"/catalogs/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -} -else { -const err50 = {instancePath:instancePath+"/catalogs",schemaPath:"#/properties/catalogs/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data.errors !== undefined){ -let data34 = data.errors; -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -for(const key9 in data34){ -if(typeof data34[key9] !== "string"){ -const err51 = {instancePath:instancePath+"/errors/" + key9.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/errors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -else { -const err52 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -} -else { -const err53 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -validate123.errors = vErrors; -return errors === 0; -} - -export const ProviderConfiguration = validate124; -const schema125 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"definition":{"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"api":{"type":"string"}},"required":["name","base_url","api"],"additionalProperties":false},"custom":{"type":"boolean"},"credential":{"type":"object","properties":{"mode":{"type":"string"},"configured":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"available":{"type":["null","boolean"]}},"required":["mode","configured"],"additionalProperties":false},"models":{"type":["null","array"],"items":{"type":"object","properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":false}},"removal_blockers":{"type":["null","array"],"items":{"type":"string"}},"discovery":{"type":["null","object"],"properties":{"status":{"type":"string"},"message":{"type":"string"},"model_count":{"type":"integer"}},"required":["status"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/ProviderConfiguration","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderConfiguration","required":["revision","provider","definition","custom","credential","models","removal_blockers"],"additionalProperties":false}; - -function validate124(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderConfiguration" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.definition === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.custom === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "custom"},message:"must have required property '"+"custom"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.credential === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "credential"},message:"must have required property '"+"credential"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.models === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.removal_blockers === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "removal_blockers"},message:"must have required property '"+"removal_blockers"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key0 in data){ -if(!((((((((key0 === "revision") || (key0 === "provider")) || (key0 === "definition")) || (key0 === "custom")) || (key0 === "credential")) || (key0 === "models")) || (key0 === "removal_blockers")) || (key0 === "discovery"))){ -const err7 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err8 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err9 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.definition !== undefined){ -let data2 = data.definition; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.base_url === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.api === undefined){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "api"},message:"must have required property '"+"api"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -for(const key1 in data2){ -if(!(((key1 === "name") || (key1 === "base_url")) || (key1 === "api"))){ -const err13 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err14 = {instancePath:instancePath+"/definition/name",schemaPath:"#/properties/definition/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data2.base_url !== undefined){ -if(typeof data2.base_url !== "string"){ -const err15 = {instancePath:instancePath+"/definition/base_url",schemaPath:"#/properties/definition/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data2.api !== undefined){ -if(typeof data2.api !== "string"){ -const err16 = {instancePath:instancePath+"/definition/api",schemaPath:"#/properties/definition/properties/api/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.custom !== undefined){ -if(typeof data.custom !== "boolean"){ -const err18 = {instancePath:instancePath+"/custom",schemaPath:"#/properties/custom/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.credential !== undefined){ -let data7 = data.credential; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.mode === undefined){ -const err19 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.configured === undefined){ -const err20 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key2 in data7){ -if(!(((((key2 === "mode") || (key2 === "configured")) || (key2 === "environment_variable")) || (key2 === "credential_path")) || (key2 === "available"))){ -const err21 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.mode !== undefined){ -if(typeof data7.mode !== "string"){ -const err22 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.configured !== undefined){ -if(typeof data7.configured !== "boolean"){ -const err23 = {instancePath:instancePath+"/credential/configured",schemaPath:"#/properties/credential/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data7.environment_variable !== undefined){ -if(typeof data7.environment_variable !== "string"){ -const err24 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.credential_path !== undefined){ -if(typeof data7.credential_path !== "string"){ -const err25 = {instancePath:instancePath+"/credential/credential_path",schemaPath:"#/properties/credential/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.available !== undefined){ -let data12 = data7.available; -if((data12 !== null) && (typeof data12 !== "boolean")){ -const err26 = {instancePath:instancePath+"/credential/available",schemaPath:"#/properties/credential/properties/available/type",keyword:"type",params:{type: schema125.properties.credential.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -else { -const err27 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.models !== undefined){ -let data13 = data.models; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err28 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: schema125.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(Array.isArray(data13)){ -const len0 = data13.length; -for(let i0=0; i0<len0; i0++){ -let data14 = data13[i0]; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.alias === undefined){ -const err29 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data14.id === undefined){ -const err30 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -for(const key3 in data14){ -if(!((((key3 === "alias") || (key3 === "id")) || (key3 === "context")) || (key3 === "max_output"))){ -const err31 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data14.alias !== undefined){ -if(typeof data14.alias !== "string"){ -const err32 = {instancePath:instancePath+"/models/" + i0+"/alias",schemaPath:"#/properties/models/items/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data14.id !== undefined){ -if(typeof data14.id !== "string"){ -const err33 = {instancePath:instancePath+"/models/" + i0+"/id",schemaPath:"#/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data14.context !== undefined){ -let data17 = data14.context; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err34 = {instancePath:instancePath+"/models/" + i0+"/context",schemaPath:"#/properties/models/items/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data14.max_output !== undefined){ -let data18 = data14.max_output; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err35 = {instancePath:instancePath+"/models/" + i0+"/max_output",schemaPath:"#/properties/models/items/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -else { -const err36 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -} -if(data.removal_blockers !== undefined){ -let data19 = data.removal_blockers; -if((data19 !== null) && (!(Array.isArray(data19)))){ -const err37 = {instancePath:instancePath+"/removal_blockers",schemaPath:"#/properties/removal_blockers/type",keyword:"type",params:{type: schema125.properties.removal_blockers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(Array.isArray(data19)){ -const len1 = data19.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data19[i1] !== "string"){ -const err38 = {instancePath:instancePath+"/removal_blockers/" + i1,schemaPath:"#/properties/removal_blockers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -} -} -if(data.discovery !== undefined){ -let data21 = data.discovery; -if((data21 !== null) && (!(data21 && typeof data21 == "object" && !Array.isArray(data21)))){ -const err39 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/type",keyword:"type",params:{type: schema125.properties.discovery.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.status === undefined){ -const err40 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -for(const key4 in data21){ -if(!(((key4 === "status") || (key4 === "message")) || (key4 === "model_count"))){ -const err41 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data21.status !== undefined){ -if(typeof data21.status !== "string"){ -const err42 = {instancePath:instancePath+"/discovery/status",schemaPath:"#/properties/discovery/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data21.message !== undefined){ -if(typeof data21.message !== "string"){ -const err43 = {instancePath:instancePath+"/discovery/message",schemaPath:"#/properties/discovery/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data21.model_count !== undefined){ -let data24 = data21.model_count; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err44 = {instancePath:instancePath+"/discovery/model_count",schemaPath:"#/properties/discovery/properties/model_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -} -} -else { -const err45 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -validate124.errors = vErrors; -return errors === 0; -} - -export const ProviderCreateParams = validate125; -const schema126 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"definition":{"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"api":{"type":"string"}},"required":["name","base_url","api"],"additionalProperties":false},"credential":{"type":"object","properties":{"mode":{"type":"string"},"key":{"type":"string"},"environment_variable":{"type":"string"}},"required":["mode"],"additionalProperties":false},"manual_model":{"type":["null","object"],"properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":false},"allow_unverified":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCreateParams","required":["revision","provider","definition","credential"],"additionalProperties":false}; - -function validate125(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.definition === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.credential === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "credential"},message:"must have required property '"+"credential"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!((((((key0 === "revision") || (key0 === "provider")) || (key0 === "definition")) || (key0 === "credential")) || (key0 === "manual_model")) || (key0 === "allow_unverified"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err6 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.definition !== undefined){ -let data2 = data.definition; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.base_url === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.api === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "api"},message:"must have required property '"+"api"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key1 in data2){ -if(!(((key1 === "name") || (key1 === "base_url")) || (key1 === "api"))){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err11 = {instancePath:instancePath+"/definition/name",schemaPath:"#/properties/definition/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data2.base_url !== undefined){ -if(typeof data2.base_url !== "string"){ -const err12 = {instancePath:instancePath+"/definition/base_url",schemaPath:"#/properties/definition/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data2.api !== undefined){ -if(typeof data2.api !== "string"){ -const err13 = {instancePath:instancePath+"/definition/api",schemaPath:"#/properties/definition/properties/api/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.credential !== undefined){ -let data6 = data.credential; -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.mode === undefined){ -const err15 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -for(const key2 in data6){ -if(!(((key2 === "mode") || (key2 === "key")) || (key2 === "environment_variable"))){ -const err16 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data6.mode !== undefined){ -if(typeof data6.mode !== "string"){ -const err17 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data6.key !== undefined){ -if(typeof data6.key !== "string"){ -const err18 = {instancePath:instancePath+"/credential/key",schemaPath:"#/properties/credential/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data6.environment_variable !== undefined){ -if(typeof data6.environment_variable !== "string"){ -const err19 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.manual_model !== undefined){ -let data10 = data.manual_model; -if((data10 !== null) && (!(data10 && typeof data10 == "object" && !Array.isArray(data10)))){ -const err21 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/type",keyword:"type",params:{type: schema126.properties.manual_model.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.alias === undefined){ -const err22 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data10.id === undefined){ -const err23 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -for(const key3 in data10){ -if(!((((key3 === "alias") || (key3 === "id")) || (key3 === "context")) || (key3 === "max_output"))){ -const err24 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data10.alias !== undefined){ -if(typeof data10.alias !== "string"){ -const err25 = {instancePath:instancePath+"/manual_model/alias",schemaPath:"#/properties/manual_model/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data10.id !== undefined){ -if(typeof data10.id !== "string"){ -const err26 = {instancePath:instancePath+"/manual_model/id",schemaPath:"#/properties/manual_model/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data10.context !== undefined){ -let data13 = data10.context; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err27 = {instancePath:instancePath+"/manual_model/context",schemaPath:"#/properties/manual_model/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data10.max_output !== undefined){ -let data14 = data10.max_output; -if(!((typeof data14 == "number") && (!(data14 % 1) && !isNaN(data14)))){ -const err28 = {instancePath:instancePath+"/manual_model/max_output",schemaPath:"#/properties/manual_model/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -if(data.allow_unverified !== undefined){ -if(typeof data.allow_unverified !== "boolean"){ -const err29 = {instancePath:instancePath+"/allow_unverified",schemaPath:"#/properties/allow_unverified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -else { -const err30 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -validate125.errors = vErrors; -return errors === 0; -} - -export const ProviderDisconnectParams = validate126; -const schema127 = {"type":"object","properties":{"provider":{"type":"string"},"revision":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderDisconnectParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderDisconnectParams","required":["provider","revision"],"additionalProperties":false}; - -function validate126(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderDisconnectParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "provider") || (key0 === "revision"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err3 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate126.errors = vErrors; -return errors === 0; -} - -export const ProviderKeySetup = validate127; -const schema128 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"key":{"type":"string"},"environment":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderKeySetup","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderKeySetup","required":["revision","provider","environment"],"additionalProperties":false}; - -function validate127(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderKeySetup" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.environment === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "environment"},message:"must have required property '"+"environment"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "revision") || (key0 === "provider")) || (key0 === "key")) || (key0 === "environment"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err5 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err6 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.environment !== undefined){ -if(typeof data.environment !== "boolean"){ -const err7 = {instancePath:instancePath+"/environment",schemaPath:"#/properties/environment/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate127.errors = vErrors; -return errors === 0; -} - -export const ProviderList = validate128; -const schema129 = {"type":"object","properties":{"revision":{"type":"string"},"discovery_error":{"type":"string"},"default_provider":{"type":"string"},"providers":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"custom":{"type":"boolean"},"methods":{"type":["null","array"],"items":{"type":"string"}},"status":{"type":"object","properties":{"provider":{"type":"string"},"configured":{"type":"boolean"},"key_source":{"type":"string"},"available":{"type":["null","boolean"]},"disabled":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"auth_method":{"type":"string"},"auth_state":{"type":"string"},"account_id":{"type":"string"},"plan":{"type":"string"},"email":{"type":"string"},"team_name":{"type":"string"},"project_id":{"type":"string"},"project_name":{"type":"string"},"machine_key_name":{"type":"string"},"warnings":{"type":["null","array"],"items":{"type":"string"}}},"required":["provider","configured","key_source","warnings"],"additionalProperties":false},"recommended":{"type":"boolean"},"suggested_model":{"type":"string"},"category":{"type":"string"},"family":{"type":"string"},"key_url":{"type":"string"}},"required":["id","name","custom","methods","status"],"additionalProperties":false}},"selection":{"type":["null","object"],"properties":{"ready":{"type":"boolean"},"model":{"type":"string"},"provider":{"type":"string"},"reason":{"type":"string"}},"required":["ready","model","provider","reason"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/ProviderList","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderList","required":["revision","providers"],"additionalProperties":false}; - -function validate128(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.providers === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "revision") || (key0 === "discovery_error")) || (key0 === "default_provider")) || (key0 === "providers")) || (key0 === "selection"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.discovery_error !== undefined){ -if(typeof data.discovery_error !== "string"){ -const err4 = {instancePath:instancePath+"/discovery_error",schemaPath:"#/properties/discovery_error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.default_provider !== undefined){ -if(typeof data.default_provider !== "string"){ -const err5 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.providers !== undefined){ -let data3 = data.providers; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err6 = {instancePath:instancePath+"/providers",schemaPath:"#/properties/providers/type",keyword:"type",params:{type: schema129.properties.providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.id === undefined){ -const err7 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4.name === undefined){ -const err8 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.custom === undefined){ -const err9 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "custom"},message:"must have required property '"+"custom"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.methods === undefined){ -const err10 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "methods"},message:"must have required property '"+"methods"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.status === undefined){ -const err11 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -for(const key1 in data4){ -if(!(func2.call(schema129.properties.providers.items.properties, key1))){ -const err12 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.id !== undefined){ -if(typeof data4.id !== "string"){ -const err13 = {instancePath:instancePath+"/providers/" + i0+"/id",schemaPath:"#/properties/providers/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err14 = {instancePath:instancePath+"/providers/" + i0+"/name",schemaPath:"#/properties/providers/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data4.custom !== undefined){ -if(typeof data4.custom !== "boolean"){ -const err15 = {instancePath:instancePath+"/providers/" + i0+"/custom",schemaPath:"#/properties/providers/items/properties/custom/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data4.methods !== undefined){ -let data8 = data4.methods; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err16 = {instancePath:instancePath+"/providers/" + i0+"/methods",schemaPath:"#/properties/providers/items/properties/methods/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.methods.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err17 = {instancePath:instancePath+"/providers/" + i0+"/methods/" + i1,schemaPath:"#/properties/providers/items/properties/methods/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data4.status !== undefined){ -let data10 = data4.status; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.provider === undefined){ -const err18 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data10.configured === undefined){ -const err19 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data10.key_source === undefined){ -const err20 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "key_source"},message:"must have required property '"+"key_source"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data10.warnings === undefined){ -const err21 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "warnings"},message:"must have required property '"+"warnings"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -for(const key2 in data10){ -if(!(func2.call(schema129.properties.providers.items.properties.status.properties, key2))){ -const err22 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data10.provider !== undefined){ -if(typeof data10.provider !== "string"){ -const err23 = {instancePath:instancePath+"/providers/" + i0+"/status/provider",schemaPath:"#/properties/providers/items/properties/status/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data10.configured !== undefined){ -if(typeof data10.configured !== "boolean"){ -const err24 = {instancePath:instancePath+"/providers/" + i0+"/status/configured",schemaPath:"#/properties/providers/items/properties/status/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data10.key_source !== undefined){ -if(typeof data10.key_source !== "string"){ -const err25 = {instancePath:instancePath+"/providers/" + i0+"/status/key_source",schemaPath:"#/properties/providers/items/properties/status/properties/key_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data10.available !== undefined){ -let data14 = data10.available; -if((data14 !== null) && (typeof data14 !== "boolean")){ -const err26 = {instancePath:instancePath+"/providers/" + i0+"/status/available",schemaPath:"#/properties/providers/items/properties/status/properties/available/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.status.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data10.disabled !== undefined){ -if(typeof data10.disabled !== "boolean"){ -const err27 = {instancePath:instancePath+"/providers/" + i0+"/status/disabled",schemaPath:"#/properties/providers/items/properties/status/properties/disabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data10.environment_variable !== undefined){ -if(typeof data10.environment_variable !== "string"){ -const err28 = {instancePath:instancePath+"/providers/" + i0+"/status/environment_variable",schemaPath:"#/properties/providers/items/properties/status/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data10.credential_path !== undefined){ -if(typeof data10.credential_path !== "string"){ -const err29 = {instancePath:instancePath+"/providers/" + i0+"/status/credential_path",schemaPath:"#/properties/providers/items/properties/status/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data10.auth_method !== undefined){ -if(typeof data10.auth_method !== "string"){ -const err30 = {instancePath:instancePath+"/providers/" + i0+"/status/auth_method",schemaPath:"#/properties/providers/items/properties/status/properties/auth_method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data10.auth_state !== undefined){ -if(typeof data10.auth_state !== "string"){ -const err31 = {instancePath:instancePath+"/providers/" + i0+"/status/auth_state",schemaPath:"#/properties/providers/items/properties/status/properties/auth_state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data10.account_id !== undefined){ -if(typeof data10.account_id !== "string"){ -const err32 = {instancePath:instancePath+"/providers/" + i0+"/status/account_id",schemaPath:"#/properties/providers/items/properties/status/properties/account_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data10.plan !== undefined){ -if(typeof data10.plan !== "string"){ -const err33 = {instancePath:instancePath+"/providers/" + i0+"/status/plan",schemaPath:"#/properties/providers/items/properties/status/properties/plan/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data10.email !== undefined){ -if(typeof data10.email !== "string"){ -const err34 = {instancePath:instancePath+"/providers/" + i0+"/status/email",schemaPath:"#/properties/providers/items/properties/status/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data10.team_name !== undefined){ -if(typeof data10.team_name !== "string"){ -const err35 = {instancePath:instancePath+"/providers/" + i0+"/status/team_name",schemaPath:"#/properties/providers/items/properties/status/properties/team_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data10.project_id !== undefined){ -if(typeof data10.project_id !== "string"){ -const err36 = {instancePath:instancePath+"/providers/" + i0+"/status/project_id",schemaPath:"#/properties/providers/items/properties/status/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data10.project_name !== undefined){ -if(typeof data10.project_name !== "string"){ -const err37 = {instancePath:instancePath+"/providers/" + i0+"/status/project_name",schemaPath:"#/properties/providers/items/properties/status/properties/project_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data10.machine_key_name !== undefined){ -if(typeof data10.machine_key_name !== "string"){ -const err38 = {instancePath:instancePath+"/providers/" + i0+"/status/machine_key_name",schemaPath:"#/properties/providers/items/properties/status/properties/machine_key_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data10.warnings !== undefined){ -let data27 = data10.warnings; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err39 = {instancePath:instancePath+"/providers/" + i0+"/status/warnings",schemaPath:"#/properties/providers/items/properties/status/properties/warnings/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.status.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err40 = {instancePath:instancePath+"/providers/" + i0+"/status/warnings/" + i2,schemaPath:"#/properties/providers/items/properties/status/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -} -} -} -else { -const err41 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data4.recommended !== undefined){ -if(typeof data4.recommended !== "boolean"){ -const err42 = {instancePath:instancePath+"/providers/" + i0+"/recommended",schemaPath:"#/properties/providers/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data4.suggested_model !== undefined){ -if(typeof data4.suggested_model !== "string"){ -const err43 = {instancePath:instancePath+"/providers/" + i0+"/suggested_model",schemaPath:"#/properties/providers/items/properties/suggested_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data4.category !== undefined){ -if(typeof data4.category !== "string"){ -const err44 = {instancePath:instancePath+"/providers/" + i0+"/category",schemaPath:"#/properties/providers/items/properties/category/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data4.family !== undefined){ -if(typeof data4.family !== "string"){ -const err45 = {instancePath:instancePath+"/providers/" + i0+"/family",schemaPath:"#/properties/providers/items/properties/family/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data4.key_url !== undefined){ -if(typeof data4.key_url !== "string"){ -const err46 = {instancePath:instancePath+"/providers/" + i0+"/key_url",schemaPath:"#/properties/providers/items/properties/key_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -else { -const err47 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -} -if(data.selection !== undefined){ -let data34 = data.selection; -if((data34 !== null) && (!(data34 && typeof data34 == "object" && !Array.isArray(data34)))){ -const err48 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/type",keyword:"type",params:{type: schema129.properties.selection.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -if(data34.ready === undefined){ -const err49 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "ready"},message:"must have required property '"+"ready"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data34.model === undefined){ -const err50 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data34.provider === undefined){ -const err51 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data34.reason === undefined){ -const err52 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -for(const key3 in data34){ -if(!((((key3 === "ready") || (key3 === "model")) || (key3 === "provider")) || (key3 === "reason"))){ -const err53 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data34.ready !== undefined){ -if(typeof data34.ready !== "boolean"){ -const err54 = {instancePath:instancePath+"/selection/ready",schemaPath:"#/properties/selection/properties/ready/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data34.model !== undefined){ -if(typeof data34.model !== "string"){ -const err55 = {instancePath:instancePath+"/selection/model",schemaPath:"#/properties/selection/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data34.provider !== undefined){ -if(typeof data34.provider !== "string"){ -const err56 = {instancePath:instancePath+"/selection/provider",schemaPath:"#/properties/selection/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data34.reason !== undefined){ -if(typeof data34.reason !== "string"){ -const err57 = {instancePath:instancePath+"/selection/reason",schemaPath:"#/properties/selection/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -} -} -} -else { -const err58 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -validate128.errors = vErrors; -return errors === 0; -} - -export const ProviderListParams = validate129; -const schema130 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderListParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderListParams","additionalProperties":false}; - -function validate129(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderListParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((key0 === "model") || (key0 === "provider"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err1 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate129.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginBeginParams = validate130; -const schema131 = {"type":"object","properties":{"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginBeginParams","additionalProperties":false}; - -function validate130(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginBeginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(key0 === "provider")){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err1 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate130.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginCreateParams = validate131; -const schema132 = {"type":"object","properties":{"flow_id":{"type":"string"},"name":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginCreateParams","required":["flow_id","name"],"additionalProperties":false}; - -function validate131(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.name === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "flow_id") || (key0 === "name"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err3 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err4 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate131.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginList = validate132; -const schema133 = {"type":"object","properties":{"flows":{"type":["null","array"],"items":{"type":"object","properties":{"flow_id":{"type":"string"},"provider":{"type":"string"},"state":{"type":"string"},"verification_url":{"type":"string"},"user_code":{"type":"string"},"email":{"type":"string"},"teams":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"projects":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"team_id":{"type":"string"},"project_id":{"type":"string"},"expires_at":{"type":"string"},"error":{"type":"string"}},"required":["flow_id","state","teams","projects","expires_at"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/ProviderLoginList","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginList","required":["flows"],"additionalProperties":false}; - -function validate132(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flows === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flows"},message:"must have required property '"+"flows"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "flows")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.flows !== undefined){ -let data0 = data.flows; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/flows",schemaPath:"#/properties/flows/type",keyword:"type",params:{type: schema133.properties.flows.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.flow_id === undefined){ -const err3 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.state === undefined){ -const err4 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.teams === undefined){ -const err5 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "teams"},message:"must have required property '"+"teams"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.projects === undefined){ -const err6 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "projects"},message:"must have required property '"+"projects"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.expires_at === undefined){ -const err7 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data1){ -if(!(func2.call(schema133.properties.flows.items.properties, key1))){ -const err8 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.flow_id !== undefined){ -if(typeof data1.flow_id !== "string"){ -const err9 = {instancePath:instancePath+"/flows/" + i0+"/flow_id",schemaPath:"#/properties/flows/items/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.provider !== undefined){ -if(typeof data1.provider !== "string"){ -const err10 = {instancePath:instancePath+"/flows/" + i0+"/provider",schemaPath:"#/properties/flows/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.state !== undefined){ -if(typeof data1.state !== "string"){ -const err11 = {instancePath:instancePath+"/flows/" + i0+"/state",schemaPath:"#/properties/flows/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.verification_url !== undefined){ -if(typeof data1.verification_url !== "string"){ -const err12 = {instancePath:instancePath+"/flows/" + i0+"/verification_url",schemaPath:"#/properties/flows/items/properties/verification_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.user_code !== undefined){ -if(typeof data1.user_code !== "string"){ -const err13 = {instancePath:instancePath+"/flows/" + i0+"/user_code",schemaPath:"#/properties/flows/items/properties/user_code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.email !== undefined){ -if(typeof data1.email !== "string"){ -const err14 = {instancePath:instancePath+"/flows/" + i0+"/email",schemaPath:"#/properties/flows/items/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.teams !== undefined){ -let data8 = data1.teams; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err15 = {instancePath:instancePath+"/flows/" + i0+"/teams",schemaPath:"#/properties/flows/items/properties/teams/type",keyword:"type",params:{type: schema133.properties.flows.items.properties.teams.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -let data9 = data8[i1]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.id === undefined){ -const err16 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data9.name === undefined){ -const err17 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key2 in data9){ -if(!((key2 === "id") || (key2 === "name"))){ -const err18 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data9.id !== undefined){ -if(typeof data9.id !== "string"){ -const err19 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1+"/id",schemaPath:"#/properties/flows/items/properties/teams/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data9.name !== undefined){ -if(typeof data9.name !== "string"){ -const err20 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1+"/name",schemaPath:"#/properties/flows/items/properties/teams/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data1.projects !== undefined){ -let data12 = data1.projects; -if((data12 !== null) && (!(Array.isArray(data12)))){ -const err22 = {instancePath:instancePath+"/flows/" + i0+"/projects",schemaPath:"#/properties/flows/items/properties/projects/type",keyword:"type",params:{type: schema133.properties.flows.items.properties.projects.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data12)){ -const len2 = data12.length; -for(let i2=0; i2<len2; i2++){ -let data13 = data12[i2]; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.id === undefined){ -const err23 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data13.name === undefined){ -const err24 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -for(const key3 in data13){ -if(!((key3 === "id") || (key3 === "name"))){ -const err25 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data13.id !== undefined){ -if(typeof data13.id !== "string"){ -const err26 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2+"/id",schemaPath:"#/properties/flows/items/properties/projects/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data13.name !== undefined){ -if(typeof data13.name !== "string"){ -const err27 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2+"/name",schemaPath:"#/properties/flows/items/properties/projects/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -else { -const err28 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -if(data1.team_id !== undefined){ -if(typeof data1.team_id !== "string"){ -const err29 = {instancePath:instancePath+"/flows/" + i0+"/team_id",schemaPath:"#/properties/flows/items/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data1.project_id !== undefined){ -if(typeof data1.project_id !== "string"){ -const err30 = {instancePath:instancePath+"/flows/" + i0+"/project_id",schemaPath:"#/properties/flows/items/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data1.expires_at !== undefined){ -if(typeof data1.expires_at !== "string"){ -const err31 = {instancePath:instancePath+"/flows/" + i0+"/expires_at",schemaPath:"#/properties/flows/items/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data1.error !== undefined){ -if(typeof data1.error !== "string"){ -const err32 = {instancePath:instancePath+"/flows/" + i0+"/error",schemaPath:"#/properties/flows/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -} -else { -const err34 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -validate132.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginParams = validate133; -const schema134 = {"type":"object","properties":{"flow_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginParams","required":["flow_id"],"additionalProperties":false}; - -function validate133(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "flow_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err2 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate133.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginProjectParams = validate134; -const schema135 = {"type":"object","properties":{"flow_id":{"type":"string"},"project_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginProjectParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginProjectParams","required":["flow_id","project_id"],"additionalProperties":false}; - -function validate134(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginProjectParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.project_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "project_id"},message:"must have required property '"+"project_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "flow_id") || (key0 === "project_id"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err3 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err4 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate134.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginStatus = validate135; -const schema136 = {"type":"object","properties":{"flow_id":{"type":"string"},"provider":{"type":"string"},"state":{"type":"string"},"verification_url":{"type":"string"},"user_code":{"type":"string"},"email":{"type":"string"},"teams":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"projects":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"team_id":{"type":"string"},"project_id":{"type":"string"},"expires_at":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginStatus","required":["flow_id","state","teams","projects","expires_at"],"additionalProperties":false}; - -function validate135(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.state === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.teams === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "teams"},message:"must have required property '"+"teams"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.projects === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "projects"},message:"must have required property '"+"projects"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.expires_at === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema136.properties, key0))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err6 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err7 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.state !== undefined){ -if(typeof data.state !== "string"){ -const err8 = {instancePath:instancePath+"/state",schemaPath:"#/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.verification_url !== undefined){ -if(typeof data.verification_url !== "string"){ -const err9 = {instancePath:instancePath+"/verification_url",schemaPath:"#/properties/verification_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.user_code !== undefined){ -if(typeof data.user_code !== "string"){ -const err10 = {instancePath:instancePath+"/user_code",schemaPath:"#/properties/user_code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.email !== undefined){ -if(typeof data.email !== "string"){ -const err11 = {instancePath:instancePath+"/email",schemaPath:"#/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.teams !== undefined){ -let data6 = data.teams; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err12 = {instancePath:instancePath+"/teams",schemaPath:"#/properties/teams/type",keyword:"type",params:{type: schema136.properties.teams.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(Array.isArray(data6)){ -const len0 = data6.length; -for(let i0=0; i0<len0; i0++){ -let data7 = data6[i0]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.id === undefined){ -const err13 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.name === undefined){ -const err14 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -for(const key1 in data7){ -if(!((key1 === "id") || (key1 === "name"))){ -const err15 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data7.id !== undefined){ -if(typeof data7.id !== "string"){ -const err16 = {instancePath:instancePath+"/teams/" + i0+"/id",schemaPath:"#/properties/teams/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data7.name !== undefined){ -if(typeof data7.name !== "string"){ -const err17 = {instancePath:instancePath+"/teams/" + i0+"/name",schemaPath:"#/properties/teams/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data.projects !== undefined){ -let data10 = data.projects; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err19 = {instancePath:instancePath+"/projects",schemaPath:"#/properties/projects/type",keyword:"type",params:{type: schema136.properties.projects.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -let data11 = data10[i1]; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.id === undefined){ -const err20 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data11.name === undefined){ -const err21 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -for(const key2 in data11){ -if(!((key2 === "id") || (key2 === "name"))){ -const err22 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data11.id !== undefined){ -if(typeof data11.id !== "string"){ -const err23 = {instancePath:instancePath+"/projects/" + i1+"/id",schemaPath:"#/properties/projects/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data11.name !== undefined){ -if(typeof data11.name !== "string"){ -const err24 = {instancePath:instancePath+"/projects/" + i1+"/name",schemaPath:"#/properties/projects/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data.team_id !== undefined){ -if(typeof data.team_id !== "string"){ -const err26 = {instancePath:instancePath+"/team_id",schemaPath:"#/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err27 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.expires_at !== undefined){ -if(typeof data.expires_at !== "string"){ -const err28 = {instancePath:instancePath+"/expires_at",schemaPath:"#/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err29 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -else { -const err30 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -validate135.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginTeamParams = validate136; -const schema137 = {"type":"object","properties":{"flow_id":{"type":"string"},"team_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginTeamParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginTeamParams","required":["flow_id","team_id"],"additionalProperties":false}; - -function validate136(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginTeamParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.team_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "team_id"},message:"must have required property '"+"team_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "flow_id") || (key0 === "team_id"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err3 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.team_id !== undefined){ -if(typeof data.team_id !== "string"){ -const err4 = {instancePath:instancePath+"/team_id",schemaPath:"#/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate136.errors = vErrors; -return errors === 0; -} - -export const ProviderNameParams = validate137; -const schema138 = {"type":"object","properties":{"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderNameParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderNameParams","required":["provider"],"additionalProperties":false}; - -function validate137(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderNameParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "provider")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate137.errors = vErrors; -return errors === 0; -} - -export const ProviderRemoveParams = validate138; -const schema139 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderRemoveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderRemoveParams","required":["revision","provider"],"additionalProperties":false}; - -function validate138(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderRemoveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "revision") || (key0 === "provider"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate138.errors = vErrors; -return errors === 0; -} - -export const ProviderRemoveResult = validate139; -const schema140 = {"type":"object","properties":{"revision":{"type":"string"},"warning":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderRemoveResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderRemoveResult","required":["revision"],"additionalProperties":false}; - -function validate139(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderRemoveResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "revision") || (key0 === "warning"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.warning !== undefined){ -if(typeof data.warning !== "string"){ -const err3 = {instancePath:instancePath+"/warning",schemaPath:"#/properties/warning/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate139.errors = vErrors; -return errors === 0; -} - -export const ProviderStatus = validate140; -const schema141 = {"type":"object","properties":{"provider":{"type":"string"},"configured":{"type":"boolean"},"key_source":{"type":"string"},"available":{"type":["null","boolean"]},"disabled":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"auth_method":{"type":"string"},"auth_state":{"type":"string"},"account_id":{"type":"string"},"plan":{"type":"string"},"email":{"type":"string"},"team_name":{"type":"string"},"project_id":{"type":"string"},"project_name":{"type":"string"},"machine_key_name":{"type":"string"},"warnings":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ProviderStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderStatus","required":["provider","configured","key_source","warnings"],"additionalProperties":false}; - -function validate140(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.configured === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.key_source === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "key_source"},message:"must have required property '"+"key_source"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.warnings === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "warnings"},message:"must have required property '"+"warnings"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema141.properties, key0))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err5 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.configured !== undefined){ -if(typeof data.configured !== "boolean"){ -const err6 = {instancePath:instancePath+"/configured",schemaPath:"#/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.key_source !== undefined){ -if(typeof data.key_source !== "string"){ -const err7 = {instancePath:instancePath+"/key_source",schemaPath:"#/properties/key_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.available !== undefined){ -let data3 = data.available; -if((data3 !== null) && (typeof data3 !== "boolean")){ -const err8 = {instancePath:instancePath+"/available",schemaPath:"#/properties/available/type",keyword:"type",params:{type: schema141.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.disabled !== undefined){ -if(typeof data.disabled !== "boolean"){ -const err9 = {instancePath:instancePath+"/disabled",schemaPath:"#/properties/disabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.environment_variable !== undefined){ -if(typeof data.environment_variable !== "string"){ -const err10 = {instancePath:instancePath+"/environment_variable",schemaPath:"#/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.credential_path !== undefined){ -if(typeof data.credential_path !== "string"){ -const err11 = {instancePath:instancePath+"/credential_path",schemaPath:"#/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.auth_method !== undefined){ -if(typeof data.auth_method !== "string"){ -const err12 = {instancePath:instancePath+"/auth_method",schemaPath:"#/properties/auth_method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.auth_state !== undefined){ -if(typeof data.auth_state !== "string"){ -const err13 = {instancePath:instancePath+"/auth_state",schemaPath:"#/properties/auth_state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.account_id !== undefined){ -if(typeof data.account_id !== "string"){ -const err14 = {instancePath:instancePath+"/account_id",schemaPath:"#/properties/account_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.plan !== undefined){ -if(typeof data.plan !== "string"){ -const err15 = {instancePath:instancePath+"/plan",schemaPath:"#/properties/plan/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.email !== undefined){ -if(typeof data.email !== "string"){ -const err16 = {instancePath:instancePath+"/email",schemaPath:"#/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.team_name !== undefined){ -if(typeof data.team_name !== "string"){ -const err17 = {instancePath:instancePath+"/team_name",schemaPath:"#/properties/team_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err18 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.project_name !== undefined){ -if(typeof data.project_name !== "string"){ -const err19 = {instancePath:instancePath+"/project_name",schemaPath:"#/properties/project_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.machine_key_name !== undefined){ -if(typeof data.machine_key_name !== "string"){ -const err20 = {instancePath:instancePath+"/machine_key_name",schemaPath:"#/properties/machine_key_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.warnings !== undefined){ -let data16 = data.warnings; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err21 = {instancePath:instancePath+"/warnings",schemaPath:"#/properties/warnings/type",keyword:"type",params:{type: schema141.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(Array.isArray(data16)){ -const len0 = data16.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data16[i0] !== "string"){ -const err22 = {instancePath:instancePath+"/warnings/" + i0,schemaPath:"#/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -} -} -else { -const err23 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -validate140.errors = vErrors; -return errors === 0; -} - -export const ProviderUpdateParams = validate141; -const schema142 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"name":{"type":["null","string"]},"base_url":{"type":["null","string"]},"credential":{"type":["null","object"],"properties":{"mode":{"type":"string"},"key":{"type":"string"},"environment_variable":{"type":"string"}},"required":["mode"],"additionalProperties":false},"manual_model":{"type":["null","object"],"properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":false},"allow_unverified":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderUpdateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderUpdateParams","required":["revision","provider"],"additionalProperties":false}; - -function validate141(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderUpdateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "revision") || (key0 === "provider")) || (key0 === "name")) || (key0 === "base_url")) || (key0 === "credential")) || (key0 === "manual_model")) || (key0 === "allow_unverified"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.name !== undefined){ -let data2 = data.name; -if((data2 !== null) && (typeof data2 !== "string")){ -const err5 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: schema142.properties.name.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.base_url !== undefined){ -let data3 = data.base_url; -if((data3 !== null) && (typeof data3 !== "string")){ -const err6 = {instancePath:instancePath+"/base_url",schemaPath:"#/properties/base_url/type",keyword:"type",params:{type: schema142.properties.base_url.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.credential !== undefined){ -let data4 = data.credential; -if((data4 !== null) && (!(data4 && typeof data4 == "object" && !Array.isArray(data4)))){ -const err7 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: schema142.properties.credential.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.mode === undefined){ -const err8 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key1 in data4){ -if(!(((key1 === "mode") || (key1 === "key")) || (key1 === "environment_variable"))){ -const err9 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data4.mode !== undefined){ -if(typeof data4.mode !== "string"){ -const err10 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data4.key !== undefined){ -if(typeof data4.key !== "string"){ -const err11 = {instancePath:instancePath+"/credential/key",schemaPath:"#/properties/credential/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data4.environment_variable !== undefined){ -if(typeof data4.environment_variable !== "string"){ -const err12 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.manual_model !== undefined){ -let data8 = data.manual_model; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err13 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/type",keyword:"type",params:{type: schema142.properties.manual_model.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.alias === undefined){ -const err14 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data8.id === undefined){ -const err15 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -for(const key2 in data8){ -if(!((((key2 === "alias") || (key2 === "id")) || (key2 === "context")) || (key2 === "max_output"))){ -const err16 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data8.alias !== undefined){ -if(typeof data8.alias !== "string"){ -const err17 = {instancePath:instancePath+"/manual_model/alias",schemaPath:"#/properties/manual_model/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data8.id !== undefined){ -if(typeof data8.id !== "string"){ -const err18 = {instancePath:instancePath+"/manual_model/id",schemaPath:"#/properties/manual_model/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data8.context !== undefined){ -let data11 = data8.context; -if(!((typeof data11 == "number") && (!(data11 % 1) && !isNaN(data11)))){ -const err19 = {instancePath:instancePath+"/manual_model/context",schemaPath:"#/properties/manual_model/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data8.max_output !== undefined){ -let data12 = data8.max_output; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err20 = {instancePath:instancePath+"/manual_model/max_output",schemaPath:"#/properties/manual_model/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -} -if(data.allow_unverified !== undefined){ -if(typeof data.allow_unverified !== "boolean"){ -const err21 = {instancePath:instancePath+"/allow_unverified",schemaPath:"#/properties/allow_unverified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -else { -const err22 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -validate141.errors = vErrors; -return errors === 0; -} - -export const ProviderValidateParams = validate142; -const schema143 = {"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"key":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderValidateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderValidateParams","required":["name","base_url","key"],"additionalProperties":false}; - -function validate142(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderValidateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.name === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.base_url === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.key === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "name") || (key0 === "base_url")) || (key0 === "key"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err4 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.base_url !== undefined){ -if(typeof data.base_url !== "string"){ -const err5 = {instancePath:instancePath+"/base_url",schemaPath:"#/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err6 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate142.errors = vErrors; -return errors === 0; -} - -export const ProviderValidateResult = validate143; -const schema144 = {"type":"object","properties":{"models":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"context_length":{"type":"integer"},"max_completion_tokens":{"type":"integer"},"reasoning_efforts":{"type":["null","array"],"items":{"type":"string"}},"pricing":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"completion":{"type":"string"},"input_cache_read":{"type":"string"}},"required":["prompt","completion"],"additionalProperties":false},"input_modalities":{"type":["null","array"],"items":{"type":"string"}},"output_modalities":{"type":["null","array"],"items":{"type":"string"}},"supports_tools":{"type":["null","boolean"]},"type":{"type":"string"}},"required":["id"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/ProviderValidateResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderValidateResult","required":["models"],"additionalProperties":false}; - -function validate143(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderValidateResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.models === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "models")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.models !== undefined){ -let data0 = data.models; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: schema144.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err3 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key1 in data1){ -if(!(func2.call(schema144.properties.models.items.properties, key1))){ -const err4 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err5 = {instancePath:instancePath+"/models/" + i0+"/id",schemaPath:"#/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.context_length !== undefined){ -let data3 = data1.context_length; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err6 = {instancePath:instancePath+"/models/" + i0+"/context_length",schemaPath:"#/properties/models/items/properties/context_length/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.max_completion_tokens !== undefined){ -let data4 = data1.max_completion_tokens; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err7 = {instancePath:instancePath+"/models/" + i0+"/max_completion_tokens",schemaPath:"#/properties/models/items/properties/max_completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.reasoning_efforts !== undefined){ -let data5 = data1.reasoning_efforts; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err8 = {instancePath:instancePath+"/models/" + i0+"/reasoning_efforts",schemaPath:"#/properties/models/items/properties/reasoning_efforts/type",keyword:"type",params:{type: schema144.properties.models.items.properties.reasoning_efforts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data5)){ -const len1 = data5.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data5[i1] !== "string"){ -const err9 = {instancePath:instancePath+"/models/" + i0+"/reasoning_efforts/" + i1,schemaPath:"#/properties/models/items/properties/reasoning_efforts/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data1.pricing !== undefined){ -let data7 = data1.pricing; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err10 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/type",keyword:"type",params:{type: schema144.properties.models.items.properties.pricing.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.prompt === undefined){ -const err11 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7.completion === undefined){ -const err12 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "completion"},message:"must have required property '"+"completion"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -for(const key2 in data7){ -if(!(((key2 === "prompt") || (key2 === "completion")) || (key2 === "input_cache_read"))){ -const err13 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data7.prompt !== undefined){ -if(typeof data7.prompt !== "string"){ -const err14 = {instancePath:instancePath+"/models/" + i0+"/pricing/prompt",schemaPath:"#/properties/models/items/properties/pricing/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data7.completion !== undefined){ -if(typeof data7.completion !== "string"){ -const err15 = {instancePath:instancePath+"/models/" + i0+"/pricing/completion",schemaPath:"#/properties/models/items/properties/pricing/properties/completion/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data7.input_cache_read !== undefined){ -if(typeof data7.input_cache_read !== "string"){ -const err16 = {instancePath:instancePath+"/models/" + i0+"/pricing/input_cache_read",schemaPath:"#/properties/models/items/properties/pricing/properties/input_cache_read/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -if(data1.input_modalities !== undefined){ -let data11 = data1.input_modalities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err17 = {instancePath:instancePath+"/models/" + i0+"/input_modalities",schemaPath:"#/properties/models/items/properties/input_modalities/type",keyword:"type",params:{type: schema144.properties.models.items.properties.input_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err18 = {instancePath:instancePath+"/models/" + i0+"/input_modalities/" + i2,schemaPath:"#/properties/models/items/properties/input_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data1.output_modalities !== undefined){ -let data13 = data1.output_modalities; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err19 = {instancePath:instancePath+"/models/" + i0+"/output_modalities",schemaPath:"#/properties/models/items/properties/output_modalities/type",keyword:"type",params:{type: schema144.properties.models.items.properties.output_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data13)){ -const len3 = data13.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data13[i3] !== "string"){ -const err20 = {instancePath:instancePath+"/models/" + i0+"/output_modalities/" + i3,schemaPath:"#/properties/models/items/properties/output_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -} -if(data1.supports_tools !== undefined){ -let data15 = data1.supports_tools; -if((data15 !== null) && (typeof data15 !== "boolean")){ -const err21 = {instancePath:instancePath+"/models/" + i0+"/supports_tools",schemaPath:"#/properties/models/items/properties/supports_tools/type",keyword:"type",params:{type: schema144.properties.models.items.properties.supports_tools.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data1.type !== undefined){ -if(typeof data1.type !== "string"){ -const err22 = {instancePath:instancePath+"/models/" + i0+"/type",schemaPath:"#/properties/models/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -} -else { -const err24 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -validate143.errors = vErrors; -return errors === 0; -} - -export const QueryParams = validate144; -const schema145 = {"type":"object","properties":{"root_id":{"type":"string"},"operation":{"type":"string"},"payload":true},"$id":"https://whip.dev/protocol/v6/QueryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"QueryParams","required":["operation"],"additionalProperties":false}; - -function validate144(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QueryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "root_id") || (key0 === "operation")) || (key0 === "payload"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err3 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate144.errors = vErrors; -return errors === 0; -} - -export const QueryResult = validate145; -const schema146 = {"type":"object","properties":{"result":true,"content":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/QueryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"QueryResult","additionalProperties":false}; - -function validate145(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QueryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(((key0 === "result") || (key0 === "content")) || (key0 === "root_id"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.content !== undefined){ -let data0 = data.content; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: schema146.properties.content.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err2 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.digest === undefined){ -const err3 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.size === undefined){ -const err4 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key1 in data0){ -if(!(((((key1 === "reference_id") || (key1 === "digest")) || (key1 === "size")) || (key1 === "media_type")) || (key1 === "source"))){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err6 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err7 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err8 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err9 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err11 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err12 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err13 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -validate145.errors = vErrors; -return errors === 0; -} - -export const QuestionAnswerParams = validate146; -const schema147 = {"type":"object","properties":{"id":{"type":"string"},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/QuestionAnswerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"QuestionAnswerParams","required":["id","answer","dismissed"],"additionalProperties":false}; - -function validate146(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QuestionAnswerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.answer === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "answer"},message:"must have required property '"+"answer"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.dismissed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "dismissed"},message:"must have required property '"+"dismissed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "id") || (key0 === "answer")) || (key0 === "dismissed")) || (key0 === "answers"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.answer !== undefined){ -let data1 = data.answer; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err5 = {instancePath:instancePath+"/answer",schemaPath:"#/properties/answer/type",keyword:"type",params:{type: schema147.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err6 = {instancePath:instancePath+"/answer/" + i0,schemaPath:"#/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -} -if(data.dismissed !== undefined){ -if(typeof data.dismissed !== "boolean"){ -const err7 = {instancePath:instancePath+"/dismissed",schemaPath:"#/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.answers !== undefined){ -let data4 = data.answers; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err8 = {instancePath:instancePath+"/answers",schemaPath:"#/properties/answers/type",keyword:"type",params:{type: schema147.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -let data5 = data4[i1]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -for(const key1 in data5){ -if(!((key1 === "answer") || (key1 === "dismissed"))){ -const err9 = {instancePath:instancePath+"/answers/" + i1,schemaPath:"#/properties/answers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data5.answer !== undefined){ -let data6 = data5.answer; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err10 = {instancePath:instancePath+"/answers/" + i1+"/answer",schemaPath:"#/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema147.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(Array.isArray(data6)){ -const len2 = data6.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data6[i2] !== "string"){ -const err11 = {instancePath:instancePath+"/answers/" + i1+"/answer/" + i2,schemaPath:"#/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -if(data5.dismissed !== undefined){ -if(typeof data5.dismissed !== "boolean"){ -const err12 = {instancePath:instancePath+"/answers/" + i1+"/dismissed",schemaPath:"#/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath:instancePath+"/answers/" + i1,schemaPath:"#/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -validate146.errors = vErrors; -return errors === 0; -} - -export const RPCError = validate147; -const schema148 = {"type":"object","properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":false},"code":{"type":"integer"},"message":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RPCError","$schema":"http://json-schema.org/draft-07/schema#","title":"RPCError","required":["code","message"],"additionalProperties":false}; - -function validate147(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RPCError" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.code === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.message === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "data") || (key0 === "code")) || (key0 === "message"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.data !== undefined){ -let data0 = data.data; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema148.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.kind === undefined){ -const err4 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key1 in data0){ -if(!(key1 === "kind")){ -const err5 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err6 = {instancePath:instancePath+"/data/kind",schemaPath:"#/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -} -if(data.code !== undefined){ -let data2 = data.code; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err7 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.message !== undefined){ -if(typeof data.message !== "string"){ -const err8 = {instancePath:instancePath+"/message",schemaPath:"#/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate147.errors = vErrors; -return errors === 0; -} - -export const ReplayParams = validate148; -const schema149 = {"type":"object","properties":{"root_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ReplayParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ReplayParams","required":["root_id","cursor"],"additionalProperties":false}; - -function validate148(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ReplayParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "root_id") || (key0 === "cursor")) || (key0 === "limit"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.limit !== undefined){ -let data2 = data.limit; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err7 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate148.errors = vErrors; -return errors === 0; -} - -export const ReplayResult = validate149; -const schema150 = {"type":"object","properties":{"events":{"type":["null","array"],"items":{"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["root_id","seq","kind"],"additionalProperties":false}},"latest":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expired":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ReplayResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ReplayResult","required":["events","latest"],"additionalProperties":false}; - -function validate149(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ReplayResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.events === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "events"},message:"must have required property '"+"events"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.latest === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "latest"},message:"must have required property '"+"latest"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "events") || (key0 === "latest")) || (key0 === "expired"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.events !== undefined){ -let data0 = data.events; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/events",schemaPath:"#/properties/events/type",keyword:"type",params:{type: schema150.properties.events.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err4 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.seq === undefined){ -const err5 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.kind === undefined){ -const err6 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key1 in data1){ -if(!(((((key1 === "subscription_id") || (key1 === "root_id")) || (key1 === "seq")) || (key1 === "kind")) || (key1 === "payload"))){ -const err7 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.subscription_id !== undefined){ -if(typeof data1.subscription_id !== "string"){ -const err8 = {instancePath:instancePath+"/events/" + i0+"/subscription_id",schemaPath:"#/properties/events/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err9 = {instancePath:instancePath+"/events/" + i0+"/root_id",schemaPath:"#/properties/events/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.seq !== undefined){ -let data4 = data1.seq; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err10 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err11 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -else { -const err12 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.kind !== undefined){ -if(typeof data1.kind !== "string"){ -const err13 = {instancePath:instancePath+"/events/" + i0+"/kind",schemaPath:"#/properties/events/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.latest !== undefined){ -let data6 = data.latest; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err15 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err16 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.expired !== undefined){ -if(typeof data.expired !== "boolean"){ -const err18 = {instancePath:instancePath+"/expired",schemaPath:"#/properties/expired/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -else { -const err19 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -validate149.errors = vErrors; -return errors === 0; -} - -export const Resolved = validate150; -const schema151 = {"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"dark":{"type":"boolean"},"colors":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"},"muted":{"type":"string"},"faint":{"type":"string"},"primary":{"type":"string"},"on_primary":{"type":"string"},"accent":{"type":"string"},"success":{"type":"string"},"warning":{"type":"string"},"error":{"type":"string"},"info":{"type":"string"},"link":{"type":"string"},"emphasis":{"type":"string"},"border":{"type":"string"},"border_focus":{"type":"string"},"diff_add":{"type":"string"},"diff_del":{"type":"string"},"panel":{"type":"string"},"element":{"type":"string"},"hover":{"type":"string"}},"required":["background","foreground","muted","faint","primary","on_primary","accent","success","warning","error","info","link","emphasis","border","border_focus","diff_add","diff_del","panel","element","hover"],"additionalProperties":false},"syntax":{"type":"object","properties":{"keyword":{"type":"string"},"string":{"type":"string"},"number":{"type":"string"},"comment":{"type":"string"},"function":{"type":"string"},"type":{"type":"string"},"operator":{"type":"string"},"punctuation":{"type":"string"}},"required":["keyword","string","number","comment","function","type","operator","punctuation"],"additionalProperties":false},"markdown":{"type":"object","properties":{"heading":{"type":"string"},"strong":{"type":"string"},"code":{"type":"string"},"quote":{"type":"string"}},"required":["heading","strong","code","quote"],"additionalProperties":false},"code":{"type":"object","properties":{"foreground":{"type":"string"},"background":{"type":"string"},"tokens":{"type":"object","additionalProperties":{"type":"object","properties":{"color":{"type":"string"},"background":{"type":"string"},"bold":{"type":"boolean"},"italic":{"type":"boolean"},"underline":{"type":"boolean"}},"required":["color","background","bold","italic","underline"],"additionalProperties":false}}},"required":["foreground","background","tokens"],"additionalProperties":false},"web":{"type":["null","object"],"properties":{"navigation":{"type":"string"},"quiet_border":{"type":"string"},"code_background":{"type":"string"},"inline_code_background":{"type":"string"}},"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/Resolved","$schema":"http://json-schema.org/draft-07/schema#","title":"Resolved","required":["id","name","dark","colors","syntax","markdown","code"],"additionalProperties":false}; - -function validate150(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Resolved" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.name === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.dark === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "dark"},message:"must have required property '"+"dark"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.colors === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "colors"},message:"must have required property '"+"colors"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.syntax === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "syntax"},message:"must have required property '"+"syntax"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.markdown === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "markdown"},message:"must have required property '"+"markdown"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.code === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key0 in data){ -if(!((((((((key0 === "id") || (key0 === "name")) || (key0 === "dark")) || (key0 === "colors")) || (key0 === "syntax")) || (key0 === "markdown")) || (key0 === "code")) || (key0 === "web"))){ -const err7 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err8 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err9 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.dark !== undefined){ -if(typeof data.dark !== "boolean"){ -const err10 = {instancePath:instancePath+"/dark",schemaPath:"#/properties/dark/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.colors !== undefined){ -let data3 = data.colors; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.background === undefined){ -const err11 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data3.foreground === undefined){ -const err12 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "foreground"},message:"must have required property '"+"foreground"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data3.muted === undefined){ -const err13 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "muted"},message:"must have required property '"+"muted"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data3.faint === undefined){ -const err14 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "faint"},message:"must have required property '"+"faint"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data3.primary === undefined){ -const err15 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "primary"},message:"must have required property '"+"primary"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data3.on_primary === undefined){ -const err16 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "on_primary"},message:"must have required property '"+"on_primary"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data3.accent === undefined){ -const err17 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "accent"},message:"must have required property '"+"accent"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data3.success === undefined){ -const err18 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "success"},message:"must have required property '"+"success"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data3.warning === undefined){ -const err19 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "warning"},message:"must have required property '"+"warning"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data3.error === undefined){ -const err20 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "error"},message:"must have required property '"+"error"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data3.info === undefined){ -const err21 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "info"},message:"must have required property '"+"info"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data3.link === undefined){ -const err22 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "link"},message:"must have required property '"+"link"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data3.emphasis === undefined){ -const err23 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "emphasis"},message:"must have required property '"+"emphasis"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data3.border === undefined){ -const err24 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "border"},message:"must have required property '"+"border"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data3.border_focus === undefined){ -const err25 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "border_focus"},message:"must have required property '"+"border_focus"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data3.diff_add === undefined){ -const err26 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "diff_add"},message:"must have required property '"+"diff_add"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data3.diff_del === undefined){ -const err27 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "diff_del"},message:"must have required property '"+"diff_del"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data3.panel === undefined){ -const err28 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "panel"},message:"must have required property '"+"panel"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data3.element === undefined){ -const err29 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "element"},message:"must have required property '"+"element"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data3.hover === undefined){ -const err30 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "hover"},message:"must have required property '"+"hover"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -for(const key1 in data3){ -if(!(func2.call(schema151.properties.colors.properties, key1))){ -const err31 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data3.background !== undefined){ -if(typeof data3.background !== "string"){ -const err32 = {instancePath:instancePath+"/colors/background",schemaPath:"#/properties/colors/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data3.foreground !== undefined){ -if(typeof data3.foreground !== "string"){ -const err33 = {instancePath:instancePath+"/colors/foreground",schemaPath:"#/properties/colors/properties/foreground/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data3.muted !== undefined){ -if(typeof data3.muted !== "string"){ -const err34 = {instancePath:instancePath+"/colors/muted",schemaPath:"#/properties/colors/properties/muted/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data3.faint !== undefined){ -if(typeof data3.faint !== "string"){ -const err35 = {instancePath:instancePath+"/colors/faint",schemaPath:"#/properties/colors/properties/faint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data3.primary !== undefined){ -if(typeof data3.primary !== "string"){ -const err36 = {instancePath:instancePath+"/colors/primary",schemaPath:"#/properties/colors/properties/primary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data3.on_primary !== undefined){ -if(typeof data3.on_primary !== "string"){ -const err37 = {instancePath:instancePath+"/colors/on_primary",schemaPath:"#/properties/colors/properties/on_primary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data3.accent !== undefined){ -if(typeof data3.accent !== "string"){ -const err38 = {instancePath:instancePath+"/colors/accent",schemaPath:"#/properties/colors/properties/accent/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data3.success !== undefined){ -if(typeof data3.success !== "string"){ -const err39 = {instancePath:instancePath+"/colors/success",schemaPath:"#/properties/colors/properties/success/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data3.warning !== undefined){ -if(typeof data3.warning !== "string"){ -const err40 = {instancePath:instancePath+"/colors/warning",schemaPath:"#/properties/colors/properties/warning/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data3.error !== undefined){ -if(typeof data3.error !== "string"){ -const err41 = {instancePath:instancePath+"/colors/error",schemaPath:"#/properties/colors/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data3.info !== undefined){ -if(typeof data3.info !== "string"){ -const err42 = {instancePath:instancePath+"/colors/info",schemaPath:"#/properties/colors/properties/info/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data3.link !== undefined){ -if(typeof data3.link !== "string"){ -const err43 = {instancePath:instancePath+"/colors/link",schemaPath:"#/properties/colors/properties/link/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data3.emphasis !== undefined){ -if(typeof data3.emphasis !== "string"){ -const err44 = {instancePath:instancePath+"/colors/emphasis",schemaPath:"#/properties/colors/properties/emphasis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data3.border !== undefined){ -if(typeof data3.border !== "string"){ -const err45 = {instancePath:instancePath+"/colors/border",schemaPath:"#/properties/colors/properties/border/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data3.border_focus !== undefined){ -if(typeof data3.border_focus !== "string"){ -const err46 = {instancePath:instancePath+"/colors/border_focus",schemaPath:"#/properties/colors/properties/border_focus/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data3.diff_add !== undefined){ -if(typeof data3.diff_add !== "string"){ -const err47 = {instancePath:instancePath+"/colors/diff_add",schemaPath:"#/properties/colors/properties/diff_add/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data3.diff_del !== undefined){ -if(typeof data3.diff_del !== "string"){ -const err48 = {instancePath:instancePath+"/colors/diff_del",schemaPath:"#/properties/colors/properties/diff_del/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data3.panel !== undefined){ -if(typeof data3.panel !== "string"){ -const err49 = {instancePath:instancePath+"/colors/panel",schemaPath:"#/properties/colors/properties/panel/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data3.element !== undefined){ -if(typeof data3.element !== "string"){ -const err50 = {instancePath:instancePath+"/colors/element",schemaPath:"#/properties/colors/properties/element/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data3.hover !== undefined){ -if(typeof data3.hover !== "string"){ -const err51 = {instancePath:instancePath+"/colors/hover",schemaPath:"#/properties/colors/properties/hover/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -else { -const err52 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data.syntax !== undefined){ -let data24 = data.syntax; -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.keyword === undefined){ -const err53 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "keyword"},message:"must have required property '"+"keyword"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data24.string === undefined){ -const err54 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "string"},message:"must have required property '"+"string"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data24.number === undefined){ -const err55 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data24.comment === undefined){ -const err56 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "comment"},message:"must have required property '"+"comment"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data24.function === undefined){ -const err57 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data24.type === undefined){ -const err58 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data24.operator === undefined){ -const err59 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "operator"},message:"must have required property '"+"operator"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data24.punctuation === undefined){ -const err60 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "punctuation"},message:"must have required property '"+"punctuation"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -for(const key2 in data24){ -if(!((((((((key2 === "keyword") || (key2 === "string")) || (key2 === "number")) || (key2 === "comment")) || (key2 === "function")) || (key2 === "type")) || (key2 === "operator")) || (key2 === "punctuation"))){ -const err61 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data24.keyword !== undefined){ -if(typeof data24.keyword !== "string"){ -const err62 = {instancePath:instancePath+"/syntax/keyword",schemaPath:"#/properties/syntax/properties/keyword/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data24.string !== undefined){ -if(typeof data24.string !== "string"){ -const err63 = {instancePath:instancePath+"/syntax/string",schemaPath:"#/properties/syntax/properties/string/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data24.number !== undefined){ -if(typeof data24.number !== "string"){ -const err64 = {instancePath:instancePath+"/syntax/number",schemaPath:"#/properties/syntax/properties/number/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data24.comment !== undefined){ -if(typeof data24.comment !== "string"){ -const err65 = {instancePath:instancePath+"/syntax/comment",schemaPath:"#/properties/syntax/properties/comment/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data24.function !== undefined){ -if(typeof data24.function !== "string"){ -const err66 = {instancePath:instancePath+"/syntax/function",schemaPath:"#/properties/syntax/properties/function/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data24.type !== undefined){ -if(typeof data24.type !== "string"){ -const err67 = {instancePath:instancePath+"/syntax/type",schemaPath:"#/properties/syntax/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data24.operator !== undefined){ -if(typeof data24.operator !== "string"){ -const err68 = {instancePath:instancePath+"/syntax/operator",schemaPath:"#/properties/syntax/properties/operator/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data24.punctuation !== undefined){ -if(typeof data24.punctuation !== "string"){ -const err69 = {instancePath:instancePath+"/syntax/punctuation",schemaPath:"#/properties/syntax/properties/punctuation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -else { -const err70 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.markdown !== undefined){ -let data33 = data.markdown; -if(data33 && typeof data33 == "object" && !Array.isArray(data33)){ -if(data33.heading === undefined){ -const err71 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "heading"},message:"must have required property '"+"heading"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data33.strong === undefined){ -const err72 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "strong"},message:"must have required property '"+"strong"+"'"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(data33.code === undefined){ -const err73 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(data33.quote === undefined){ -const err74 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "quote"},message:"must have required property '"+"quote"+"'"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -for(const key3 in data33){ -if(!((((key3 === "heading") || (key3 === "strong")) || (key3 === "code")) || (key3 === "quote"))){ -const err75 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data33.heading !== undefined){ -if(typeof data33.heading !== "string"){ -const err76 = {instancePath:instancePath+"/markdown/heading",schemaPath:"#/properties/markdown/properties/heading/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data33.strong !== undefined){ -if(typeof data33.strong !== "string"){ -const err77 = {instancePath:instancePath+"/markdown/strong",schemaPath:"#/properties/markdown/properties/strong/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data33.code !== undefined){ -if(typeof data33.code !== "string"){ -const err78 = {instancePath:instancePath+"/markdown/code",schemaPath:"#/properties/markdown/properties/code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data33.quote !== undefined){ -if(typeof data33.quote !== "string"){ -const err79 = {instancePath:instancePath+"/markdown/quote",schemaPath:"#/properties/markdown/properties/quote/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -} -else { -const err80 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.code !== undefined){ -let data38 = data.code; -if(data38 && typeof data38 == "object" && !Array.isArray(data38)){ -if(data38.foreground === undefined){ -const err81 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "foreground"},message:"must have required property '"+"foreground"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data38.background === undefined){ -const err82 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data38.tokens === undefined){ -const err83 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -for(const key4 in data38){ -if(!(((key4 === "foreground") || (key4 === "background")) || (key4 === "tokens"))){ -const err84 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data38.foreground !== undefined){ -if(typeof data38.foreground !== "string"){ -const err85 = {instancePath:instancePath+"/code/foreground",schemaPath:"#/properties/code/properties/foreground/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data38.background !== undefined){ -if(typeof data38.background !== "string"){ -const err86 = {instancePath:instancePath+"/code/background",schemaPath:"#/properties/code/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data38.tokens !== undefined){ -let data41 = data38.tokens; -if(data41 && typeof data41 == "object" && !Array.isArray(data41)){ -for(const key5 in data41){ -let data42 = data41[key5]; -if(data42 && typeof data42 == "object" && !Array.isArray(data42)){ -if(data42.color === undefined){ -const err87 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "color"},message:"must have required property '"+"color"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(data42.background === undefined){ -const err88 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(data42.bold === undefined){ -const err89 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "bold"},message:"must have required property '"+"bold"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(data42.italic === undefined){ -const err90 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "italic"},message:"must have required property '"+"italic"+"'"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -if(data42.underline === undefined){ -const err91 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "underline"},message:"must have required property '"+"underline"+"'"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -for(const key6 in data42){ -if(!(((((key6 === "color") || (key6 === "background")) || (key6 === "bold")) || (key6 === "italic")) || (key6 === "underline"))){ -const err92 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data42.color !== undefined){ -if(typeof data42.color !== "string"){ -const err93 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/color",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/color/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data42.background !== undefined){ -if(typeof data42.background !== "string"){ -const err94 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/background",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data42.bold !== undefined){ -if(typeof data42.bold !== "boolean"){ -const err95 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/bold",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/bold/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data42.italic !== undefined){ -if(typeof data42.italic !== "boolean"){ -const err96 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/italic",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/italic/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data42.underline !== undefined){ -if(typeof data42.underline !== "boolean"){ -const err97 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1")+"/underline",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/underline/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -else { -const err98 = {instancePath:instancePath+"/code/tokens/" + key5.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -else { -const err99 = {instancePath:instancePath+"/code/tokens",schemaPath:"#/properties/code/properties/tokens/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -} -else { -const err100 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data.web !== undefined){ -let data48 = data.web; -if((data48 !== null) && (!(data48 && typeof data48 == "object" && !Array.isArray(data48)))){ -const err101 = {instancePath:instancePath+"/web",schemaPath:"#/properties/web/type",keyword:"type",params:{type: schema151.properties.web.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -for(const key7 in data48){ -if(!((((key7 === "navigation") || (key7 === "quiet_border")) || (key7 === "code_background")) || (key7 === "inline_code_background"))){ -const err102 = {instancePath:instancePath+"/web",schemaPath:"#/properties/web/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data48.navigation !== undefined){ -if(typeof data48.navigation !== "string"){ -const err103 = {instancePath:instancePath+"/web/navigation",schemaPath:"#/properties/web/properties/navigation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data48.quiet_border !== undefined){ -if(typeof data48.quiet_border !== "string"){ -const err104 = {instancePath:instancePath+"/web/quiet_border",schemaPath:"#/properties/web/properties/quiet_border/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data48.code_background !== undefined){ -if(typeof data48.code_background !== "string"){ -const err105 = {instancePath:instancePath+"/web/code_background",schemaPath:"#/properties/web/properties/code_background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data48.inline_code_background !== undefined){ -if(typeof data48.inline_code_background !== "string"){ -const err106 = {instancePath:instancePath+"/web/inline_code_background",schemaPath:"#/properties/web/properties/inline_code_background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -} -} -} -else { -const err107 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -validate150.errors = vErrors; -return errors === 0; -} - -export const RestartNotice = validate151; -const schema152 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cursors":{"type":"object","additionalProperties":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}}},"$id":"https://whip.dev/protocol/v6/RestartNotice","$schema":"http://json-schema.org/draft-07/schema#","title":"RestartNotice","required":["generation","cursors"],"additionalProperties":false}; - -function validate151(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RestartNotice" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursors === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursors"},message:"must have required property '"+"cursors"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "generation") || (key0 === "cursors"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cursors !== undefined){ -let data1 = data.cursors; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key1 in data1){ -let data2 = data1[key1]; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err6 = {instancePath:instancePath+"/cursors/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err7 = {instancePath:instancePath+"/cursors/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/cursors/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath:instancePath+"/cursors",schemaPath:"#/properties/cursors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate151.errors = vErrors; -return errors === 0; -} - -export const RestartParams = validate152; -const schema153 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/RestartParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RestartParams","required":["generation"],"additionalProperties":false}; - -function validate152(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RestartParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "generation")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate152.errors = vErrors; -return errors === 0; -} - -export const RewindParams = validate153; -const schema154 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cut":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RewindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RewindParams","required":["expected_revision","cut"],"additionalProperties":false}; - -function validate153(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RewindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.expected_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_revision"},message:"must have required property '"+"expected_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cut === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cut"},message:"must have required property '"+"cut"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "expected_revision") || (key0 === "cut"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err3 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema154.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err4 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err5 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -if(data.cut !== undefined){ -let data1 = data.cut; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err6 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate153.errors = vErrors; -return errors === 0; -} - -export const RewindResult = validate154; -const schema155 = {"type":"object","properties":{"cut":{"type":"integer"},"restored_files":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RewindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"RewindResult","required":["cut","restored_files"],"additionalProperties":false}; - -function validate154(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RewindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cut === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cut"},message:"must have required property '"+"cut"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.restored_files === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "restored_files"},message:"must have required property '"+"restored_files"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "cut") || (key0 === "restored_files"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cut !== undefined){ -let data0 = data.cut; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err3 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.restored_files !== undefined){ -let data1 = data.restored_files; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err4 = {instancePath:instancePath+"/restored_files",schemaPath:"#/properties/restored_files/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate154.errors = vErrors; -return errors === 0; -} - -export const RootCollectionPage = validate155; -const schema156 = {"type":"object","properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"event_cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"allOf":[{"type":"object","properties":{"agent":{"type":["null","object"],"properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":false},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":false},"inbox":{"type":["null","object"],"properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["kind","content"],"additionalProperties":false}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":false},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":false},"blackboard":{"type":["null","object"],"properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["key","version","author_agent_id","payload"],"additionalProperties":false},"budget":{"type":["null","object"],"properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":false}},"required":["agent_id","state"],"additionalProperties":false},"capability":{"type":["null","object"],"properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":false}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":false},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":false},"schedule":{"type":["null","object"],"properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":false},"permission":{"type":["null","object"],"properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":false},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"additionalProperties":false},{"oneOf":[{"type":"object","properties":{"agent":{"type":["null","object"],"properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":false},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":false}},"required":["agent"],"additionalProperties":false},{"type":"object","properties":{"inbox":{"type":["null","object"],"properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["kind","content"],"additionalProperties":false}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":false},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":false}},"required":["inbox"],"additionalProperties":false},{"type":"object","properties":{"blackboard":{"type":["null","object"],"properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["key","version","author_agent_id","payload"],"additionalProperties":false}},"required":["blackboard"],"additionalProperties":false},{"type":"object","properties":{"budget":{"type":["null","object"],"properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":false}},"required":["agent_id","state"],"additionalProperties":false}},"required":["budget"],"additionalProperties":false},{"type":"object","properties":{"capability":{"type":["null","object"],"properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":false}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":false},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":false}},"required":["capability"],"additionalProperties":false},{"type":"object","properties":{"schedule":{"type":["null","object"],"properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":false}},"required":["schedule"],"additionalProperties":false},{"type":"object","properties":{"permission":{"type":["null","object"],"properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":false}},"required":["permission"],"additionalProperties":false},{"type":"object","properties":{"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["body"],"additionalProperties":false}]}]}},"next_cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","collection","revision","offset"],"additionalProperties":false},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/RootCollectionPage","$schema":"http://json-schema.org/draft-07/schema#","title":"RootCollectionPage","required":["root_id","collection","revision","event_cursor","items","has_more"],"additionalProperties":false}; - -function validate155(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootCollectionPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.collection === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.event_cursor === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "event_cursor"},message:"must have required property '"+"event_cursor"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.items === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.has_more === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "root_id") || (key0 === "collection")) || (key0 === "revision")) || (key0 === "event_cursor")) || (key0 === "items")) || (key0 === "next_cursor")) || (key0 === "has_more"))){ -const err6 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.collection !== undefined){ -if(typeof data.collection !== "string"){ -const err8 = {instancePath:instancePath+"/collection",schemaPath:"#/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.revision !== undefined){ -let data2 = data.revision; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err9 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err10 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.event_cursor !== undefined){ -let data3 = data.event_cursor; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err12 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err13 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -else { -const err14 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.items !== undefined){ -let data4 = data.items; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err15 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema156.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -let data5 = data4[i0]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -for(const key1 in data5){ -if(!((((((((key1 === "agent") || (key1 === "inbox")) || (key1 === "blackboard")) || (key1 === "budget")) || (key1 === "capability")) || (key1 === "schedule")) || (key1 === "permission")) || (key1 === "body"))){ -const err16 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/0/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data5.agent !== undefined){ -let data6 = data5.agent; -if((data6 !== null) && (!(data6 && typeof data6 == "object" && !Array.isArray(data6)))){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.execution_engine === undefined){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data6.id === undefined){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data6.root_id === undefined){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data6.parent_id === undefined){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data6.name === undefined){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data6.model === undefined){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data6.provider === undefined){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data6.effort === undefined){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data6.cwd === undefined){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data6.report === undefined){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data6.status === undefined){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data6.pending_mail === undefined){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data6.lifecycle_phase === undefined){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data6.blocking_reason === undefined){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data6.terminal_cause === undefined){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data6.allowed_controls === undefined){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -for(const key2 in data6){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.agent.properties, key2))){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data6.execution_engine !== undefined){ -if(typeof data6.execution_engine !== "string"){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/agent/execution_engine",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data6.last_turn !== undefined){ -let data8 = data6.last_turn; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.status === undefined){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data8.event_seq === undefined){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -for(const key3 in data8){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties, key3))){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data8.turn_id !== undefined){ -if(typeof data8.turn_id !== "string"){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/turn_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data8.status !== undefined){ -if(typeof data8.status !== "string"){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/status",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data8.started_at !== undefined){ -if(typeof data8.started_at !== "string"){ -const err42 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/started_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data8.finished_at !== undefined){ -if(typeof data8.finished_at !== "string"){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/finished_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data8.event_seq !== undefined){ -let data13 = data8.event_seq; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err45 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -else { -const err46 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data8.error !== undefined){ -if(typeof data8.error !== "string"){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data8.error_truncated !== undefined){ -if(typeof data8.error_truncated !== "boolean"){ -const err48 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_truncated",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data8.error_details !== undefined){ -let data16 = data8.error_details; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.reference_id === undefined){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data16.digest === undefined){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data16.size === undefined){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data16.media_type === undefined){ -const err53 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data16.source === undefined){ -const err54 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -for(const key4 in data16){ -if(!((((((((key4 === "inline") || (key4 === "text")) || (key4 === "binary")) || (key4 === "reference_id")) || (key4 === "digest")) || (key4 === "size")) || (key4 === "media_type")) || (key4 === "source"))){ -const err55 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data16.text !== undefined){ -let data17 = data16.text; -if((data17 !== null) && (typeof data17 !== "string")){ -const err56 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/text",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data16.binary !== undefined){ -let data18 = data16.binary; -if((typeof data18 !== "string") && (data18 !== null)){ -const err57 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data16.reference_id !== undefined){ -if(typeof data16.reference_id !== "string"){ -const err58 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data16.digest !== undefined){ -if(typeof data16.digest !== "string"){ -const err59 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data16.size !== undefined){ -let data21 = data16.size; -if(typeof data21 === "string"){ -if(!pattern0.test(data21)){ -const err60 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(!(formats0.validate(data21))){ -const err61 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -else { -const err62 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data16.media_type !== undefined){ -if(typeof data16.media_type !== "string"){ -const err63 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data16.source !== undefined){ -if(typeof data16.source !== "string"){ -const err64 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/source",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data8.model_calls !== undefined){ -let data24 = data8.model_calls; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err65 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/model_calls",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data8.compactions !== undefined){ -let data25 = data8.compactions; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err66 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/compactions",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data8.last_activity_at !== undefined){ -if(typeof data8.last_activity_at !== "string"){ -const err67 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -} -if(data6.id !== undefined){ -if(typeof data6.id !== "string"){ -const err68 = {instancePath:instancePath+"/items/" + i0+"/agent/id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data6.root_id !== undefined){ -if(typeof data6.root_id !== "string"){ -const err69 = {instancePath:instancePath+"/items/" + i0+"/agent/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data6.parent_id !== undefined){ -if(typeof data6.parent_id !== "string"){ -const err70 = {instancePath:instancePath+"/items/" + i0+"/agent/parent_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data6.name !== undefined){ -if(typeof data6.name !== "string"){ -const err71 = {instancePath:instancePath+"/items/" + i0+"/agent/name",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data6.model !== undefined){ -if(typeof data6.model !== "string"){ -const err72 = {instancePath:instancePath+"/items/" + i0+"/agent/model",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data6.provider !== undefined){ -if(typeof data6.provider !== "string"){ -const err73 = {instancePath:instancePath+"/items/" + i0+"/agent/provider",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data6.effort !== undefined){ -if(typeof data6.effort !== "string"){ -const err74 = {instancePath:instancePath+"/items/" + i0+"/agent/effort",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data6.cwd !== undefined){ -if(typeof data6.cwd !== "string"){ -const err75 = {instancePath:instancePath+"/items/" + i0+"/agent/cwd",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data6.report !== undefined){ -if(typeof data6.report !== "string"){ -const err76 = {instancePath:instancePath+"/items/" + i0+"/agent/report",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data6.status !== undefined){ -if(typeof data6.status !== "string"){ -const err77 = {instancePath:instancePath+"/items/" + i0+"/agent/status",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data6.pending_mail !== undefined){ -let data37 = data6.pending_mail; -if(!((typeof data37 == "number") && (!(data37 % 1) && !isNaN(data37)))){ -const err78 = {instancePath:instancePath+"/items/" + i0+"/agent/pending_mail",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data6.lifecycle_phase !== undefined){ -if(typeof data6.lifecycle_phase !== "string"){ -const err79 = {instancePath:instancePath+"/items/" + i0+"/agent/lifecycle_phase",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data6.blocking_reason !== undefined){ -if(typeof data6.blocking_reason !== "string"){ -const err80 = {instancePath:instancePath+"/items/" + i0+"/agent/blocking_reason",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data6.terminal_cause !== undefined){ -if(typeof data6.terminal_cause !== "string"){ -const err81 = {instancePath:instancePath+"/items/" + i0+"/agent/terminal_cause",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data6.allowed_controls !== undefined){ -let data41 = data6.allowed_controls; -if((data41 !== null) && (!(Array.isArray(data41)))){ -const err82 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(Array.isArray(data41)){ -const len1 = data41.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data41[i1] !== "string"){ -const err83 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls/" + i1,schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -} -} -} -} -if(data5.inbox !== undefined){ -let data43 = data5.inbox; -if((data43 !== null) && (!(data43 && typeof data43 == "object" && !Array.isArray(data43)))){ -const err84 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data43 && typeof data43 == "object" && !Array.isArray(data43)){ -if(data43.root_id === undefined){ -const err85 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data43.agent_id === undefined){ -const err86 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data43.seq === undefined){ -const err87 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(data43.kind === undefined){ -const err88 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(data43.status === undefined){ -const err89 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(data43.payload === undefined){ -const err90 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -for(const key5 in data43){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.inbox.properties, key5))){ -const err91 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data43.delivery_seq !== undefined){ -let data44 = data43.delivery_seq; -if(typeof data44 === "string"){ -if(!pattern0.test(data44)){ -const err92 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -if(!(formats0.validate(data44))){ -const err93 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -else { -const err94 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data43.origin !== undefined){ -if(typeof data43.origin !== "string"){ -const err95 = {instancePath:instancePath+"/items/" + i0+"/inbox/origin",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data43.command_client_id !== undefined){ -if(typeof data43.command_client_id !== "string"){ -const err96 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_client_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data43.command_id !== undefined){ -if(typeof data43.command_id !== "string"){ -const err97 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data43.steer_turn_id !== undefined){ -if(typeof data43.steer_turn_id !== "string"){ -const err98 = {instancePath:instancePath+"/items/" + i0+"/inbox/steer_turn_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data43.preview !== undefined){ -let data49 = data43.preview; -if((data49 !== null) && (!(data49 && typeof data49 == "object" && !Array.isArray(data49)))){ -const err99 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -if(data49 && typeof data49 == "object" && !Array.isArray(data49)){ -if(data49.text === undefined){ -const err100 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -for(const key6 in data49){ -if(!(((((key6 === "design_context") || (key6 === "text")) || (key6 === "truncated")) || (key6 === "attachments")) || (key6 === "attachment_count"))){ -const err101 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data49.design_context !== undefined){ -let data50 = data49.design_context; -if((data50 !== null) && (!(data50 && typeof data50 == "object" && !Array.isArray(data50)))){ -const err102 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(data50 && typeof data50 == "object" && !Array.isArray(data50)){ -if(data50.context_attachment_id === undefined){ -const err103 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -if(data50.elements === undefined){ -const err104 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -if(data50.element_count === undefined){ -const err105 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -for(const key7 in data50){ -if(!((((((key7 === "context_attachment_id") || (key7 === "screenshot_attachment_id")) || (key7 === "elements")) || (key7 === "element_count")) || (key7 === "page_url")) || (key7 === "page_title"))){ -const err106 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data50.context_attachment_id !== undefined){ -if(typeof data50.context_attachment_id !== "string"){ -const err107 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/context_attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data50.screenshot_attachment_id !== undefined){ -if(typeof data50.screenshot_attachment_id !== "string"){ -const err108 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data50.elements !== undefined){ -let data53 = data50.elements; -if((data53 !== null) && (!(Array.isArray(data53)))){ -const err109 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -if(Array.isArray(data53)){ -const len2 = data53.length; -for(let i2=0; i2<len2; i2++){ -let data54 = data53[i2]; -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.label === undefined){ -const err110 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -for(const key8 in data54){ -if(!((key8 === "label") || (key8 === "selector"))){ -const err111 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data54.label !== undefined){ -if(typeof data54.label !== "string"){ -const err112 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2+"/label",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data54.selector !== undefined){ -if(typeof data54.selector !== "string"){ -const err113 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2+"/selector",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -} -else { -const err114 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -} -} -if(data50.element_count !== undefined){ -let data57 = data50.element_count; -if(!((typeof data57 == "number") && (!(data57 % 1) && !isNaN(data57)))){ -const err115 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/element_count",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data50.page_url !== undefined){ -if(typeof data50.page_url !== "string"){ -const err116 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_url",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data50.page_title !== undefined){ -if(typeof data50.page_title !== "string"){ -const err117 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_title",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -} -} -if(data49.text !== undefined){ -if(typeof data49.text !== "string"){ -const err118 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -if(data49.truncated !== undefined){ -if(typeof data49.truncated !== "boolean"){ -const err119 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/truncated",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -if(data49.attachments !== undefined){ -let data62 = data49.attachments; -if((data62 !== null) && (!(Array.isArray(data62)))){ -const err120 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(Array.isArray(data62)){ -const len3 = data62.length; -for(let i3=0; i3<len3; i3++){ -let data63 = data62[i3]; -if(data63 && typeof data63 == "object" && !Array.isArray(data63)){ -if(data63.kind === undefined){ -const err121 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data63.content === undefined){ -const err122 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -for(const key9 in data63){ -if(!(((key9 === "kind") || (key9 === "name")) || (key9 === "content"))){ -const err123 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data63.kind !== undefined){ -if(typeof data63.kind !== "string"){ -const err124 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/kind",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data63.name !== undefined){ -if(typeof data63.name !== "string"){ -const err125 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/name",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data63.content !== undefined){ -let data66 = data63.content; -if(data66 && typeof data66 == "object" && !Array.isArray(data66)){ -if(data66.reference_id === undefined){ -const err126 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(data66.digest === undefined){ -const err127 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -if(data66.size === undefined){ -const err128 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -if(data66.media_type === undefined){ -const err129 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -if(data66.source === undefined){ -const err130 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -for(const key10 in data66){ -if(!((((((((key10 === "inline") || (key10 === "text")) || (key10 === "binary")) || (key10 === "reference_id")) || (key10 === "digest")) || (key10 === "size")) || (key10 === "media_type")) || (key10 === "source"))){ -const err131 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -if(data66.text !== undefined){ -let data67 = data66.text; -if((data67 !== null) && (typeof data67 !== "string")){ -const err132 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data66.binary !== undefined){ -let data68 = data66.binary; -if((typeof data68 !== "string") && (data68 !== null)){ -const err133 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/binary",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data66.reference_id !== undefined){ -if(typeof data66.reference_id !== "string"){ -const err134 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data66.digest !== undefined){ -if(typeof data66.digest !== "string"){ -const err135 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/digest",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -if(data66.size !== undefined){ -let data71 = data66.size; -if(typeof data71 === "string"){ -if(!pattern0.test(data71)){ -const err136 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -if(!(formats0.validate(data71))){ -const err137 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -else { -const err138 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -if(data66.media_type !== undefined){ -if(typeof data66.media_type !== "string"){ -const err139 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -if(data66.source !== undefined){ -if(typeof data66.source !== "string"){ -const err140 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/source",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -} -else { -const err141 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -} -else { -const err142 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -} -} -if(data49.attachment_count !== undefined){ -let data74 = data49.attachment_count; -if(!((typeof data74 == "number") && (!(data74 % 1) && !isNaN(data74)))){ -const err143 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachment_count",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -} -} -if(data43.root_id !== undefined){ -if(typeof data43.root_id !== "string"){ -const err144 = {instancePath:instancePath+"/items/" + i0+"/inbox/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -if(data43.agent_id !== undefined){ -if(typeof data43.agent_id !== "string"){ -const err145 = {instancePath:instancePath+"/items/" + i0+"/inbox/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -if(data43.seq !== undefined){ -let data77 = data43.seq; -if(typeof data77 === "string"){ -if(!pattern0.test(data77)){ -const err146 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -if(!(formats0.validate(data77))){ -const err147 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -else { -const err148 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data43.kind !== undefined){ -if(typeof data43.kind !== "string"){ -const err149 = {instancePath:instancePath+"/items/" + i0+"/inbox/kind",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -if(data43.status !== undefined){ -if(typeof data43.status !== "string"){ -const err150 = {instancePath:instancePath+"/items/" + i0+"/inbox/status",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -if(data43.payload !== undefined){ -let data80 = data43.payload; -if(data80 && typeof data80 == "object" && !Array.isArray(data80)){ -if(data80.reference_id === undefined){ -const err151 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -if(data80.digest === undefined){ -const err152 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -if(data80.size === undefined){ -const err153 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -if(data80.media_type === undefined){ -const err154 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -if(data80.source === undefined){ -const err155 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -for(const key11 in data80){ -if(!((((((((key11 === "inline") || (key11 === "text")) || (key11 === "binary")) || (key11 === "reference_id")) || (key11 === "digest")) || (key11 === "size")) || (key11 === "media_type")) || (key11 === "source"))){ -const err156 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -} -if(data80.text !== undefined){ -let data81 = data80.text; -if((data81 !== null) && (typeof data81 !== "string")){ -const err157 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -} -if(data80.binary !== undefined){ -let data82 = data80.binary; -if((typeof data82 !== "string") && (data82 !== null)){ -const err158 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/binary",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -} -if(data80.reference_id !== undefined){ -if(typeof data80.reference_id !== "string"){ -const err159 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -} -if(data80.digest !== undefined){ -if(typeof data80.digest !== "string"){ -const err160 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/digest",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data80.size !== undefined){ -let data85 = data80.size; -if(typeof data85 === "string"){ -if(!pattern0.test(data85)){ -const err161 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -if(!(formats0.validate(data85))){ -const err162 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -} -else { -const err163 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -} -if(data80.media_type !== undefined){ -if(typeof data80.media_type !== "string"){ -const err164 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data80.source !== undefined){ -if(typeof data80.source !== "string"){ -const err165 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/source",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -} -else { -const err166 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -} -} -if(data5.blackboard !== undefined){ -let data88 = data5.blackboard; -if((data88 !== null) && (!(data88 && typeof data88 == "object" && !Array.isArray(data88)))){ -const err167 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -if(data88 && typeof data88 == "object" && !Array.isArray(data88)){ -if(data88.key === undefined){ -const err168 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -if(data88.version === undefined){ -const err169 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -if(data88.author_agent_id === undefined){ -const err170 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -if(data88.payload === undefined){ -const err171 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -for(const key12 in data88){ -if(!((((key12 === "key") || (key12 === "version")) || (key12 === "author_agent_id")) || (key12 === "payload"))){ -const err172 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -} -if(data88.key !== undefined){ -if(typeof data88.key !== "string"){ -const err173 = {instancePath:instancePath+"/items/" + i0+"/blackboard/key",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -if(data88.version !== undefined){ -let data90 = data88.version; -if(typeof data90 === "string"){ -if(!pattern0.test(data90)){ -const err174 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -if(!(formats0.validate(data90))){ -const err175 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -} -else { -const err176 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -} -if(data88.author_agent_id !== undefined){ -if(typeof data88.author_agent_id !== "string"){ -const err177 = {instancePath:instancePath+"/items/" + i0+"/blackboard/author_agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -if(data88.payload !== undefined){ -let data92 = data88.payload; -if(data92 && typeof data92 == "object" && !Array.isArray(data92)){ -if(data92.reference_id === undefined){ -const err178 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -if(data92.digest === undefined){ -const err179 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -if(data92.size === undefined){ -const err180 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -if(data92.media_type === undefined){ -const err181 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -if(data92.source === undefined){ -const err182 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -for(const key13 in data92){ -if(!((((((((key13 === "inline") || (key13 === "text")) || (key13 === "binary")) || (key13 === "reference_id")) || (key13 === "digest")) || (key13 === "size")) || (key13 === "media_type")) || (key13 === "source"))){ -const err183 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -} -if(data92.text !== undefined){ -let data93 = data92.text; -if((data93 !== null) && (typeof data93 !== "string")){ -const err184 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/text",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -} -if(data92.binary !== undefined){ -let data94 = data92.binary; -if((typeof data94 !== "string") && (data94 !== null)){ -const err185 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/binary",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -if(data92.reference_id !== undefined){ -if(typeof data92.reference_id !== "string"){ -const err186 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -} -if(data92.digest !== undefined){ -if(typeof data92.digest !== "string"){ -const err187 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/digest",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -} -if(data92.size !== undefined){ -let data97 = data92.size; -if(typeof data97 === "string"){ -if(!pattern0.test(data97)){ -const err188 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -if(!(formats0.validate(data97))){ -const err189 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -} -else { -const err190 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -} -if(data92.media_type !== undefined){ -if(typeof data92.media_type !== "string"){ -const err191 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -} -if(data92.source !== undefined){ -if(typeof data92.source !== "string"){ -const err192 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/source",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -} -} -else { -const err193 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -} -} -} -if(data5.budget !== undefined){ -let data100 = data5.budget; -if((data100 !== null) && (!(data100 && typeof data100 == "object" && !Array.isArray(data100)))){ -const err194 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -if(data100 && typeof data100 == "object" && !Array.isArray(data100)){ -if(data100.agent_id === undefined){ -const err195 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(data100.state === undefined){ -const err196 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -for(const key14 in data100){ -if(!((key14 === "agent_id") || (key14 === "state"))){ -const err197 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -} -if(data100.agent_id !== undefined){ -if(typeof data100.agent_id !== "string"){ -const err198 = {instancePath:instancePath+"/items/" + i0+"/budget/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -} -if(data100.state !== undefined){ -let data102 = data100.state; -if(data102 && typeof data102 == "object" && !Array.isArray(data102)){ -if(data102.kind === undefined){ -const err199 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -if(data102.limit === undefined){ -const err200 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -if(data102.used === undefined){ -const err201 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -if(data102.reserved === undefined){ -const err202 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -if(data102.remaining === undefined){ -const err203 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -if(data102.uncertain === undefined){ -const err204 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -if(data102.incomplete === undefined){ -const err205 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -for(const key15 in data102){ -if(!(((((((key15 === "kind") || (key15 === "limit")) || (key15 === "used")) || (key15 === "reserved")) || (key15 === "remaining")) || (key15 === "uncertain")) || (key15 === "incomplete"))){ -const err206 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -} -if(data102.kind !== undefined){ -if(typeof data102.kind !== "string"){ -const err207 = {instancePath:instancePath+"/items/" + i0+"/budget/state/kind",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -} -if(data102.limit !== undefined){ -let data104 = data102.limit; -if((typeof data104 !== "string") && (data104 !== null)){ -const err208 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -if(typeof data104 === "string"){ -if(!pattern0.test(data104)){ -const err209 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -if(!(formats0.validate(data104))){ -const err210 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -} -} -if(data102.used !== undefined){ -let data105 = data102.used; -if(typeof data105 === "string"){ -if(!pattern0.test(data105)){ -const err211 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -if(!(formats0.validate(data105))){ -const err212 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -} -else { -const err213 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -} -if(data102.reserved !== undefined){ -let data106 = data102.reserved; -if(typeof data106 === "string"){ -if(!pattern0.test(data106)){ -const err214 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -if(!(formats0.validate(data106))){ -const err215 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -} -else { -const err216 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -} -if(data102.remaining !== undefined){ -let data107 = data102.remaining; -if((typeof data107 !== "string") && (data107 !== null)){ -const err217 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -if(typeof data107 === "string"){ -if(!pattern0.test(data107)){ -const err218 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -if(!(formats0.validate(data107))){ -const err219 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -} -} -if(data102.uncertain !== undefined){ -let data108 = data102.uncertain; -if(typeof data108 === "string"){ -if(!pattern0.test(data108)){ -const err220 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -if(!(formats0.validate(data108))){ -const err221 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -} -else { -const err222 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -} -if(data102.incomplete !== undefined){ -if(typeof data102.incomplete !== "boolean"){ -const err223 = {instancePath:instancePath+"/items/" + i0+"/budget/state/incomplete",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -} -} -else { -const err224 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -} -} -} -if(data5.capability !== undefined){ -let data110 = data5.capability; -if((data110 !== null) && (!(data110 && typeof data110 == "object" && !Array.isArray(data110)))){ -const err225 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -if(data110 && typeof data110 == "object" && !Array.isArray(data110)){ -if(data110.id === undefined){ -const err226 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -if(data110.root_id === undefined){ -const err227 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -if(data110.agent_id === undefined){ -const err228 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -if(data110.issuer_agent_id === undefined){ -const err229 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -if(data110.operations === undefined){ -const err230 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -if(data110.scopes === undefined){ -const err231 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -if(data110.mcp === undefined){ -const err232 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -if(data110.mcp_all === undefined){ -const err233 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -if(data110.generation === undefined){ -const err234 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -if(data110.status === undefined){ -const err235 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -if(data110.expires_at === undefined){ -const err236 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -if(data110.created_at === undefined){ -const err237 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -if(data110.updated_at === undefined){ -const err238 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -for(const key16 in data110){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.capability.properties, key16))){ -const err239 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -} -if(data110.id !== undefined){ -if(typeof data110.id !== "string"){ -const err240 = {instancePath:instancePath+"/items/" + i0+"/capability/id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data110.root_id !== undefined){ -if(typeof data110.root_id !== "string"){ -const err241 = {instancePath:instancePath+"/items/" + i0+"/capability/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data110.agent_id !== undefined){ -if(typeof data110.agent_id !== "string"){ -const err242 = {instancePath:instancePath+"/items/" + i0+"/capability/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -} -if(data110.issuer_agent_id !== undefined){ -if(typeof data110.issuer_agent_id !== "string"){ -const err243 = {instancePath:instancePath+"/items/" + i0+"/capability/issuer_agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -} -if(data110.operations !== undefined){ -let data115 = data110.operations; -if((data115 !== null) && (!(Array.isArray(data115)))){ -const err244 = {instancePath:instancePath+"/items/" + i0+"/capability/operations",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/operations/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -if(Array.isArray(data115)){ -const len4 = data115.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data115[i4] !== "string"){ -const err245 = {instancePath:instancePath+"/items/" + i0+"/capability/operations/" + i4,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -} -} -} -if(data110.scopes !== undefined){ -let data117 = data110.scopes; -if((data117 !== null) && (!(Array.isArray(data117)))){ -const err246 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/scopes/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -if(Array.isArray(data117)){ -const len5 = data117.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data117[i5] !== "string"){ -const err247 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes/" + i5,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -} -} -} -if(data110.file_scope !== undefined){ -if(typeof data110.file_scope !== "string"){ -const err248 = {instancePath:instancePath+"/items/" + i0+"/capability/file_scope",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -} -if(data110.file_issuer_id !== undefined){ -if(typeof data110.file_issuer_id !== "string"){ -const err249 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -} -if(data110.file_issuer_generation !== undefined){ -let data121 = data110.file_issuer_generation; -if(typeof data121 === "string"){ -if(!pattern0.test(data121)){ -const err250 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -if(!(formats0.validate(data121))){ -const err251 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -} -else { -const err252 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -} -if(data110.mcp !== undefined){ -let data122 = data110.mcp; -if((data122 !== null) && (!(Array.isArray(data122)))){ -const err253 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -if(Array.isArray(data122)){ -const len6 = data122.length; -for(let i6=0; i6<len6; i6++){ -let data123 = data122[i6]; -if(data123 && typeof data123 == "object" && !Array.isArray(data123)){ -if(data123.server === undefined){ -const err254 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -if(data123.tool === undefined){ -const err255 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -if(data123.definition === undefined){ -const err256 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -for(const key17 in data123){ -if(!(((key17 === "server") || (key17 === "tool")) || (key17 === "definition"))){ -const err257 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key17},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -} -if(data123.server !== undefined){ -if(typeof data123.server !== "string"){ -const err258 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/server",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -} -if(data123.tool !== undefined){ -if(typeof data123.tool !== "string"){ -const err259 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/tool",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -} -if(data123.definition !== undefined){ -if(typeof data123.definition !== "string"){ -const err260 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/definition",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -} -} -else { -const err261 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -} -} -} -if(data110.mcp_all !== undefined){ -if(typeof data110.mcp_all !== "boolean"){ -const err262 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp_all",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -} -if(data110.browser !== undefined){ -let data128 = data110.browser; -if((data128 !== null) && (!(data128 && typeof data128 == "object" && !Array.isArray(data128)))){ -const err263 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -if(data128 && typeof data128 == "object" && !Array.isArray(data128)){ -if(data128.provider_id === undefined){ -const err264 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -if(data128.provider_epoch === undefined){ -const err265 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -if(data128.tab_id === undefined){ -const err266 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -if(data128.tab_generation === undefined){ -const err267 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -if(data128.profile_id === undefined){ -const err268 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -if(data128.rights === undefined){ -const err269 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -for(const key18 in data128){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties, key18))){ -const err270 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key18},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -} -if(data128.provider_id !== undefined){ -if(typeof data128.provider_id !== "string"){ -const err271 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -} -if(data128.provider_epoch !== undefined){ -if(typeof data128.provider_epoch !== "string"){ -const err272 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_epoch",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -} -if(data128.tab_id !== undefined){ -if(typeof data128.tab_id !== "string"){ -const err273 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -} -if(data128.tab_generation !== undefined){ -if(typeof data128.tab_generation !== "string"){ -const err274 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -} -if(data128.profile_id !== undefined){ -if(typeof data128.profile_id !== "string"){ -const err275 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/profile_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -} -if(data128.attachment_id !== undefined){ -if(typeof data128.attachment_id !== "string"){ -const err276 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -} -if(data128.attachment_generation !== undefined){ -if(typeof data128.attachment_generation !== "string"){ -const err277 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -} -if(data128.rights !== undefined){ -let data136 = data128.rights; -if((data136 !== null) && (!(Array.isArray(data136)))){ -const err278 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/rights/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -if(Array.isArray(data136)){ -const len7 = data136.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data136[i7] !== "string"){ -const err279 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights/" + i7,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -} -} -} -if(data128.preview !== undefined){ -let data138 = data128.preview; -if((data138 !== null) && (!(data138 && typeof data138 == "object" && !Array.isArray(data138)))){ -const err280 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -if(data138 && typeof data138 == "object" && !Array.isArray(data138)){ -if(data138.host_id === undefined){ -const err281 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -if(data138.host_identity === undefined){ -const err282 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -if(data138.connection_generation === undefined){ -const err283 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -if(data138.environment_id === undefined){ -const err284 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -if(data138.loopback === undefined){ -const err285 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -if(data138.ports === undefined){ -const err286 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -for(const key19 in data138){ -if(!((((((key19 === "host_id") || (key19 === "host_identity")) || (key19 === "connection_generation")) || (key19 === "environment_id")) || (key19 === "loopback")) || (key19 === "ports"))){ -const err287 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key19},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -} -if(data138.host_id !== undefined){ -if(typeof data138.host_id !== "string"){ -const err288 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -} -if(data138.host_identity !== undefined){ -if(typeof data138.host_identity !== "string"){ -const err289 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_identity",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -} -if(data138.connection_generation !== undefined){ -if(typeof data138.connection_generation !== "string"){ -const err290 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/connection_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -} -if(data138.environment_id !== undefined){ -if(typeof data138.environment_id !== "string"){ -const err291 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/environment_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data138.loopback !== undefined){ -if(typeof data138.loopback !== "string"){ -const err292 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/loopback",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -} -if(data138.ports !== undefined){ -let data144 = data138.ports; -if((data144 !== null) && (!(Array.isArray(data144)))){ -const err293 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -if(Array.isArray(data144)){ -const len8 = data144.length; -for(let i8=0; i8<len8; i8++){ -let data145 = data144[i8]; -if(!((typeof data145 == "number") && (!(data145 % 1) && !isNaN(data145)))){ -const err294 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports/" + i8,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -} -} -} -} -} -} -} -if(data110.browser_issuer_id !== undefined){ -if(typeof data110.browser_issuer_id !== "string"){ -const err295 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -} -if(data110.browser_issuer_generation !== undefined){ -let data147 = data110.browser_issuer_generation; -if(!((typeof data147 == "number") && (!(data147 % 1) && !isNaN(data147)))){ -const err296 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -} -if(data110.browser_delegation_only !== undefined){ -if(typeof data110.browser_delegation_only !== "boolean"){ -const err297 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_delegation_only",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -} -if(data110.generation !== undefined){ -let data149 = data110.generation; -if(typeof data149 === "string"){ -if(!pattern0.test(data149)){ -const err298 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -if(!(formats0.validate(data149))){ -const err299 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -} -else { -const err300 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -} -if(data110.status !== undefined){ -if(typeof data110.status !== "string"){ -const err301 = {instancePath:instancePath+"/items/" + i0+"/capability/status",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -} -if(data110.expires_at !== undefined){ -if(typeof data110.expires_at !== "string"){ -const err302 = {instancePath:instancePath+"/items/" + i0+"/capability/expires_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -} -if(data110.created_at !== undefined){ -if(typeof data110.created_at !== "string"){ -const err303 = {instancePath:instancePath+"/items/" + i0+"/capability/created_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -} -if(data110.updated_at !== undefined){ -if(typeof data110.updated_at !== "string"){ -const err304 = {instancePath:instancePath+"/items/" + i0+"/capability/updated_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -} -} -} -if(data5.schedule !== undefined){ -let data154 = data5.schedule; -if((data154 !== null) && (!(data154 && typeof data154 == "object" && !Array.isArray(data154)))){ -const err305 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.schedule.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -if(data154 && typeof data154 == "object" && !Array.isArray(data154)){ -if(data154.id === undefined){ -const err306 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -if(data154.schedule === undefined){ -const err307 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -if(data154.prompt === undefined){ -const err308 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -if(data154.anchor === undefined){ -const err309 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -if(data154.last_fire === undefined){ -const err310 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -for(const key20 in data154){ -if(!(((((key20 === "id") || (key20 === "schedule")) || (key20 === "prompt")) || (key20 === "anchor")) || (key20 === "last_fire"))){ -const err311 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key20},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -} -if(data154.id !== undefined){ -let data155 = data154.id; -if(!((typeof data155 == "number") && (!(data155 % 1) && !isNaN(data155)))){ -const err312 = {instancePath:instancePath+"/items/" + i0+"/schedule/id",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -} -if(data154.schedule !== undefined){ -if(typeof data154.schedule !== "string"){ -const err313 = {instancePath:instancePath+"/items/" + i0+"/schedule/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -} -if(data154.prompt !== undefined){ -if(typeof data154.prompt !== "string"){ -const err314 = {instancePath:instancePath+"/items/" + i0+"/schedule/prompt",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -} -if(data154.anchor !== undefined){ -if(typeof data154.anchor !== "string"){ -const err315 = {instancePath:instancePath+"/items/" + i0+"/schedule/anchor",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -} -if(data154.last_fire !== undefined){ -if(typeof data154.last_fire !== "string"){ -const err316 = {instancePath:instancePath+"/items/" + i0+"/schedule/last_fire",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -} -} -} -if(data5.permission !== undefined){ -let data160 = data5.permission; -if((data160 !== null) && (!(data160 && typeof data160 == "object" && !Array.isArray(data160)))){ -const err317 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.permission.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -if(data160 && typeof data160 == "object" && !Array.isArray(data160)){ -if(data160.id === undefined){ -const err318 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -if(data160.agent_id === undefined){ -const err319 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -if(data160.operation_id === undefined){ -const err320 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -if(data160.operation === undefined){ -const err321 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -if(data160.canonical_path === undefined){ -const err322 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -if(data160.request_digest === undefined){ -const err323 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -if(data160.capability_id === undefined){ -const err324 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -if(data160.capability_generation === undefined){ -const err325 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -if(data160.status === undefined){ -const err326 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -if(data160.command === undefined){ -const err327 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -if(data160.rule === undefined){ -const err328 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -for(const key21 in data160){ -if(!(func2.call(schema156.properties.items.items.allOf[0].properties.permission.properties, key21))){ -const err329 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key21},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -} -if(data160.id !== undefined){ -if(typeof data160.id !== "string"){ -const err330 = {instancePath:instancePath+"/items/" + i0+"/permission/id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -} -if(data160.agent_id !== undefined){ -if(typeof data160.agent_id !== "string"){ -const err331 = {instancePath:instancePath+"/items/" + i0+"/permission/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -} -if(data160.operation_id !== undefined){ -if(typeof data160.operation_id !== "string"){ -const err332 = {instancePath:instancePath+"/items/" + i0+"/permission/operation_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -} -if(data160.operation !== undefined){ -if(typeof data160.operation !== "string"){ -const err333 = {instancePath:instancePath+"/items/" + i0+"/permission/operation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -} -if(data160.canonical_path !== undefined){ -if(typeof data160.canonical_path !== "string"){ -const err334 = {instancePath:instancePath+"/items/" + i0+"/permission/canonical_path",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -} -if(data160.request_digest !== undefined){ -if(typeof data160.request_digest !== "string"){ -const err335 = {instancePath:instancePath+"/items/" + i0+"/permission/request_digest",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -if(data160.capability_id !== undefined){ -if(typeof data160.capability_id !== "string"){ -const err336 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -} -if(data160.capability_generation !== undefined){ -let data168 = data160.capability_generation; -if(typeof data168 === "string"){ -if(!pattern0.test(data168)){ -const err337 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -if(!(formats0.validate(data168))){ -const err338 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -} -else { -const err339 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -} -if(data160.status !== undefined){ -if(typeof data160.status !== "string"){ -const err340 = {instancePath:instancePath+"/items/" + i0+"/permission/status",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -} -if(data160.command !== undefined){ -if(typeof data160.command !== "string"){ -const err341 = {instancePath:instancePath+"/items/" + i0+"/permission/command",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -} -if(data160.rule !== undefined){ -if(typeof data160.rule !== "string"){ -const err342 = {instancePath:instancePath+"/items/" + i0+"/permission/rule",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -} -} -} -if(data5.body !== undefined){ -let data172 = data5.body; -if((data172 !== null) && (!(data172 && typeof data172 == "object" && !Array.isArray(data172)))){ -const err343 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -if(data172 && typeof data172 == "object" && !Array.isArray(data172)){ -if(data172.reference_id === undefined){ -const err344 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -if(data172.digest === undefined){ -const err345 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -if(data172.size === undefined){ -const err346 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -if(data172.media_type === undefined){ -const err347 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -if(data172.source === undefined){ -const err348 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -for(const key22 in data172){ -if(!((((((((key22 === "inline") || (key22 === "text")) || (key22 === "binary")) || (key22 === "reference_id")) || (key22 === "digest")) || (key22 === "size")) || (key22 === "media_type")) || (key22 === "source"))){ -const err349 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key22},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -} -if(data172.text !== undefined){ -let data173 = data172.text; -if((data173 !== null) && (typeof data173 !== "string")){ -const err350 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -} -if(data172.binary !== undefined){ -let data174 = data172.binary; -if((typeof data174 !== "string") && (data174 !== null)){ -const err351 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -} -if(data172.reference_id !== undefined){ -if(typeof data172.reference_id !== "string"){ -const err352 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -} -if(data172.digest !== undefined){ -if(typeof data172.digest !== "string"){ -const err353 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -} -if(data172.size !== undefined){ -let data177 = data172.size; -if(typeof data177 === "string"){ -if(!pattern0.test(data177)){ -const err354 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -if(!(formats0.validate(data177))){ -const err355 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -} -else { -const err356 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -} -if(data172.media_type !== undefined){ -if(typeof data172.media_type !== "string"){ -const err357 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -} -if(data172.source !== undefined){ -if(typeof data172.source !== "string"){ -const err358 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -} -} -} -} -else { -const err359 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -const _errs386 = errors; -let valid42 = false; -let passing0 = null; -const _errs387 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.agent === undefined){ -const err360 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/required",keyword:"required",params:{missingProperty: "agent"},message:"must have required property '"+"agent"+"'"}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -for(const key23 in data5){ -if(!(key23 === "agent")){ -const err361 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key23},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -} -if(data5.agent !== undefined){ -let data180 = data5.agent; -if((data180 !== null) && (!(data180 && typeof data180 == "object" && !Array.isArray(data180)))){ -const err362 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -if(data180 && typeof data180 == "object" && !Array.isArray(data180)){ -if(data180.execution_engine === undefined){ -const err363 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -if(data180.id === undefined){ -const err364 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -if(data180.root_id === undefined){ -const err365 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -if(data180.parent_id === undefined){ -const err366 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -if(data180.name === undefined){ -const err367 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -if(data180.model === undefined){ -const err368 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -if(data180.provider === undefined){ -const err369 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -if(data180.effort === undefined){ -const err370 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -if(data180.cwd === undefined){ -const err371 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -if(data180.report === undefined){ -const err372 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -if(data180.status === undefined){ -const err373 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -if(data180.pending_mail === undefined){ -const err374 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -if(data180.lifecycle_phase === undefined){ -const err375 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -if(data180.blocking_reason === undefined){ -const err376 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -if(data180.terminal_cause === undefined){ -const err377 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -if(data180.allowed_controls === undefined){ -const err378 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -for(const key24 in data180){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties, key24))){ -const err379 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key24},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -} -if(data180.execution_engine !== undefined){ -if(typeof data180.execution_engine !== "string"){ -const err380 = {instancePath:instancePath+"/items/" + i0+"/agent/execution_engine",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -} -if(data180.last_turn !== undefined){ -let data182 = data180.last_turn; -if((data182 !== null) && (!(data182 && typeof data182 == "object" && !Array.isArray(data182)))){ -const err381 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -if(data182 && typeof data182 == "object" && !Array.isArray(data182)){ -if(data182.status === undefined){ -const err382 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -if(data182.event_seq === undefined){ -const err383 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -for(const key25 in data182){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties, key25))){ -const err384 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key25},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -} -if(data182.turn_id !== undefined){ -if(typeof data182.turn_id !== "string"){ -const err385 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/turn_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -} -if(data182.status !== undefined){ -if(typeof data182.status !== "string"){ -const err386 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -if(data182.started_at !== undefined){ -if(typeof data182.started_at !== "string"){ -const err387 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/started_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -} -if(data182.finished_at !== undefined){ -if(typeof data182.finished_at !== "string"){ -const err388 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/finished_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err388]; -} -else { -vErrors.push(err388); -} -errors++; -} -} -if(data182.event_seq !== undefined){ -let data187 = data182.event_seq; -if(typeof data187 === "string"){ -if(!pattern0.test(data187)){ -const err389 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err389]; -} -else { -vErrors.push(err389); -} -errors++; -} -if(!(formats0.validate(data187))){ -const err390 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err390]; -} -else { -vErrors.push(err390); -} -errors++; -} -} -else { -const err391 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err391]; -} -else { -vErrors.push(err391); -} -errors++; -} -} -if(data182.error !== undefined){ -if(typeof data182.error !== "string"){ -const err392 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err392]; -} -else { -vErrors.push(err392); -} -errors++; -} -} -if(data182.error_truncated !== undefined){ -if(typeof data182.error_truncated !== "boolean"){ -const err393 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_truncated",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err393]; -} -else { -vErrors.push(err393); -} -errors++; -} -} -if(data182.error_details !== undefined){ -let data190 = data182.error_details; -if((data190 !== null) && (!(data190 && typeof data190 == "object" && !Array.isArray(data190)))){ -const err394 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err394]; -} -else { -vErrors.push(err394); -} -errors++; -} -if(data190 && typeof data190 == "object" && !Array.isArray(data190)){ -if(data190.reference_id === undefined){ -const err395 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err395]; -} -else { -vErrors.push(err395); -} -errors++; -} -if(data190.digest === undefined){ -const err396 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err396]; -} -else { -vErrors.push(err396); -} -errors++; -} -if(data190.size === undefined){ -const err397 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err397]; -} -else { -vErrors.push(err397); -} -errors++; -} -if(data190.media_type === undefined){ -const err398 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err398]; -} -else { -vErrors.push(err398); -} -errors++; -} -if(data190.source === undefined){ -const err399 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err399]; -} -else { -vErrors.push(err399); -} -errors++; -} -for(const key26 in data190){ -if(!((((((((key26 === "inline") || (key26 === "text")) || (key26 === "binary")) || (key26 === "reference_id")) || (key26 === "digest")) || (key26 === "size")) || (key26 === "media_type")) || (key26 === "source"))){ -const err400 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key26},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err400]; -} -else { -vErrors.push(err400); -} -errors++; -} -} -if(data190.text !== undefined){ -let data191 = data190.text; -if((data191 !== null) && (typeof data191 !== "string")){ -const err401 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err401]; -} -else { -vErrors.push(err401); -} -errors++; -} -} -if(data190.binary !== undefined){ -let data192 = data190.binary; -if((typeof data192 !== "string") && (data192 !== null)){ -const err402 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err402]; -} -else { -vErrors.push(err402); -} -errors++; -} -} -if(data190.reference_id !== undefined){ -if(typeof data190.reference_id !== "string"){ -const err403 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err403]; -} -else { -vErrors.push(err403); -} -errors++; -} -} -if(data190.digest !== undefined){ -if(typeof data190.digest !== "string"){ -const err404 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err404]; -} -else { -vErrors.push(err404); -} -errors++; -} -} -if(data190.size !== undefined){ -let data195 = data190.size; -if(typeof data195 === "string"){ -if(!pattern0.test(data195)){ -const err405 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err405]; -} -else { -vErrors.push(err405); -} -errors++; -} -if(!(formats0.validate(data195))){ -const err406 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err406]; -} -else { -vErrors.push(err406); -} -errors++; -} -} -else { -const err407 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err407]; -} -else { -vErrors.push(err407); -} -errors++; -} -} -if(data190.media_type !== undefined){ -if(typeof data190.media_type !== "string"){ -const err408 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err408]; -} -else { -vErrors.push(err408); -} -errors++; -} -} -if(data190.source !== undefined){ -if(typeof data190.source !== "string"){ -const err409 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err409]; -} -else { -vErrors.push(err409); -} -errors++; -} -} -} -} -if(data182.model_calls !== undefined){ -let data198 = data182.model_calls; -if(!((typeof data198 == "number") && (!(data198 % 1) && !isNaN(data198)))){ -const err410 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/model_calls",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err410]; -} -else { -vErrors.push(err410); -} -errors++; -} -} -if(data182.compactions !== undefined){ -let data199 = data182.compactions; -if(!((typeof data199 == "number") && (!(data199 % 1) && !isNaN(data199)))){ -const err411 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/compactions",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err411]; -} -else { -vErrors.push(err411); -} -errors++; -} -} -if(data182.last_activity_at !== undefined){ -if(typeof data182.last_activity_at !== "string"){ -const err412 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err412]; -} -else { -vErrors.push(err412); -} -errors++; -} -} -} -} -if(data180.id !== undefined){ -if(typeof data180.id !== "string"){ -const err413 = {instancePath:instancePath+"/items/" + i0+"/agent/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err413]; -} -else { -vErrors.push(err413); -} -errors++; -} -} -if(data180.root_id !== undefined){ -if(typeof data180.root_id !== "string"){ -const err414 = {instancePath:instancePath+"/items/" + i0+"/agent/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err414]; -} -else { -vErrors.push(err414); -} -errors++; -} -} -if(data180.parent_id !== undefined){ -if(typeof data180.parent_id !== "string"){ -const err415 = {instancePath:instancePath+"/items/" + i0+"/agent/parent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err415]; -} -else { -vErrors.push(err415); -} -errors++; -} -} -if(data180.name !== undefined){ -if(typeof data180.name !== "string"){ -const err416 = {instancePath:instancePath+"/items/" + i0+"/agent/name",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err416]; -} -else { -vErrors.push(err416); -} -errors++; -} -} -if(data180.model !== undefined){ -if(typeof data180.model !== "string"){ -const err417 = {instancePath:instancePath+"/items/" + i0+"/agent/model",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err417]; -} -else { -vErrors.push(err417); -} -errors++; -} -} -if(data180.provider !== undefined){ -if(typeof data180.provider !== "string"){ -const err418 = {instancePath:instancePath+"/items/" + i0+"/agent/provider",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err418]; -} -else { -vErrors.push(err418); -} -errors++; -} -} -if(data180.effort !== undefined){ -if(typeof data180.effort !== "string"){ -const err419 = {instancePath:instancePath+"/items/" + i0+"/agent/effort",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err419]; -} -else { -vErrors.push(err419); -} -errors++; -} -} -if(data180.cwd !== undefined){ -if(typeof data180.cwd !== "string"){ -const err420 = {instancePath:instancePath+"/items/" + i0+"/agent/cwd",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err420]; -} -else { -vErrors.push(err420); -} -errors++; -} -} -if(data180.report !== undefined){ -if(typeof data180.report !== "string"){ -const err421 = {instancePath:instancePath+"/items/" + i0+"/agent/report",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err421]; -} -else { -vErrors.push(err421); -} -errors++; -} -} -if(data180.status !== undefined){ -if(typeof data180.status !== "string"){ -const err422 = {instancePath:instancePath+"/items/" + i0+"/agent/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err422]; -} -else { -vErrors.push(err422); -} -errors++; -} -} -if(data180.pending_mail !== undefined){ -let data211 = data180.pending_mail; -if(!((typeof data211 == "number") && (!(data211 % 1) && !isNaN(data211)))){ -const err423 = {instancePath:instancePath+"/items/" + i0+"/agent/pending_mail",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err423]; -} -else { -vErrors.push(err423); -} -errors++; -} -} -if(data180.lifecycle_phase !== undefined){ -if(typeof data180.lifecycle_phase !== "string"){ -const err424 = {instancePath:instancePath+"/items/" + i0+"/agent/lifecycle_phase",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err424]; -} -else { -vErrors.push(err424); -} -errors++; -} -} -if(data180.blocking_reason !== undefined){ -if(typeof data180.blocking_reason !== "string"){ -const err425 = {instancePath:instancePath+"/items/" + i0+"/agent/blocking_reason",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err425]; -} -else { -vErrors.push(err425); -} -errors++; -} -} -if(data180.terminal_cause !== undefined){ -if(typeof data180.terminal_cause !== "string"){ -const err426 = {instancePath:instancePath+"/items/" + i0+"/agent/terminal_cause",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err426]; -} -else { -vErrors.push(err426); -} -errors++; -} -} -if(data180.allowed_controls !== undefined){ -let data215 = data180.allowed_controls; -if((data215 !== null) && (!(Array.isArray(data215)))){ -const err427 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err427]; -} -else { -vErrors.push(err427); -} -errors++; -} -if(Array.isArray(data215)){ -const len9 = data215.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data215[i9] !== "string"){ -const err428 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls/" + i9,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err428]; -} -else { -vErrors.push(err428); -} -errors++; -} -} -} -} -} -} -} -else { -const err429 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err429]; -} -else { -vErrors.push(err429); -} -errors++; -} -var _valid0 = _errs387 === errors; -if(_valid0){ -valid42 = true; -passing0 = 0; -} -const _errs467 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.inbox === undefined){ -const err430 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/required",keyword:"required",params:{missingProperty: "inbox"},message:"must have required property '"+"inbox"+"'"}; -if(vErrors === null){ -vErrors = [err430]; -} -else { -vErrors.push(err430); -} -errors++; -} -for(const key27 in data5){ -if(!(key27 === "inbox")){ -const err431 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key27},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err431]; -} -else { -vErrors.push(err431); -} -errors++; -} -} -if(data5.inbox !== undefined){ -let data217 = data5.inbox; -if((data217 !== null) && (!(data217 && typeof data217 == "object" && !Array.isArray(data217)))){ -const err432 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err432]; -} -else { -vErrors.push(err432); -} -errors++; -} -if(data217 && typeof data217 == "object" && !Array.isArray(data217)){ -if(data217.root_id === undefined){ -const err433 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err433]; -} -else { -vErrors.push(err433); -} -errors++; -} -if(data217.agent_id === undefined){ -const err434 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err434]; -} -else { -vErrors.push(err434); -} -errors++; -} -if(data217.seq === undefined){ -const err435 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err435]; -} -else { -vErrors.push(err435); -} -errors++; -} -if(data217.kind === undefined){ -const err436 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err436]; -} -else { -vErrors.push(err436); -} -errors++; -} -if(data217.status === undefined){ -const err437 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err437]; -} -else { -vErrors.push(err437); -} -errors++; -} -if(data217.payload === undefined){ -const err438 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err438]; -} -else { -vErrors.push(err438); -} -errors++; -} -for(const key28 in data217){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties, key28))){ -const err439 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key28},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err439]; -} -else { -vErrors.push(err439); -} -errors++; -} -} -if(data217.delivery_seq !== undefined){ -let data218 = data217.delivery_seq; -if(typeof data218 === "string"){ -if(!pattern0.test(data218)){ -const err440 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err440]; -} -else { -vErrors.push(err440); -} -errors++; -} -if(!(formats0.validate(data218))){ -const err441 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err441]; -} -else { -vErrors.push(err441); -} -errors++; -} -} -else { -const err442 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err442]; -} -else { -vErrors.push(err442); -} -errors++; -} -} -if(data217.origin !== undefined){ -if(typeof data217.origin !== "string"){ -const err443 = {instancePath:instancePath+"/items/" + i0+"/inbox/origin",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err443]; -} -else { -vErrors.push(err443); -} -errors++; -} -} -if(data217.command_client_id !== undefined){ -if(typeof data217.command_client_id !== "string"){ -const err444 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_client_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err444]; -} -else { -vErrors.push(err444); -} -errors++; -} -} -if(data217.command_id !== undefined){ -if(typeof data217.command_id !== "string"){ -const err445 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err445]; -} -else { -vErrors.push(err445); -} -errors++; -} -} -if(data217.steer_turn_id !== undefined){ -if(typeof data217.steer_turn_id !== "string"){ -const err446 = {instancePath:instancePath+"/items/" + i0+"/inbox/steer_turn_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err446]; -} -else { -vErrors.push(err446); -} -errors++; -} -} -if(data217.preview !== undefined){ -let data223 = data217.preview; -if((data223 !== null) && (!(data223 && typeof data223 == "object" && !Array.isArray(data223)))){ -const err447 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err447]; -} -else { -vErrors.push(err447); -} -errors++; -} -if(data223 && typeof data223 == "object" && !Array.isArray(data223)){ -if(data223.text === undefined){ -const err448 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err448]; -} -else { -vErrors.push(err448); -} -errors++; -} -for(const key29 in data223){ -if(!(((((key29 === "design_context") || (key29 === "text")) || (key29 === "truncated")) || (key29 === "attachments")) || (key29 === "attachment_count"))){ -const err449 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key29},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err449]; -} -else { -vErrors.push(err449); -} -errors++; -} -} -if(data223.design_context !== undefined){ -let data224 = data223.design_context; -if((data224 !== null) && (!(data224 && typeof data224 == "object" && !Array.isArray(data224)))){ -const err450 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err450]; -} -else { -vErrors.push(err450); -} -errors++; -} -if(data224 && typeof data224 == "object" && !Array.isArray(data224)){ -if(data224.context_attachment_id === undefined){ -const err451 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err451]; -} -else { -vErrors.push(err451); -} -errors++; -} -if(data224.elements === undefined){ -const err452 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err452]; -} -else { -vErrors.push(err452); -} -errors++; -} -if(data224.element_count === undefined){ -const err453 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err453]; -} -else { -vErrors.push(err453); -} -errors++; -} -for(const key30 in data224){ -if(!((((((key30 === "context_attachment_id") || (key30 === "screenshot_attachment_id")) || (key30 === "elements")) || (key30 === "element_count")) || (key30 === "page_url")) || (key30 === "page_title"))){ -const err454 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key30},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err454]; -} -else { -vErrors.push(err454); -} -errors++; -} -} -if(data224.context_attachment_id !== undefined){ -if(typeof data224.context_attachment_id !== "string"){ -const err455 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/context_attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err455]; -} -else { -vErrors.push(err455); -} -errors++; -} -} -if(data224.screenshot_attachment_id !== undefined){ -if(typeof data224.screenshot_attachment_id !== "string"){ -const err456 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err456]; -} -else { -vErrors.push(err456); -} -errors++; -} -} -if(data224.elements !== undefined){ -let data227 = data224.elements; -if((data227 !== null) && (!(Array.isArray(data227)))){ -const err457 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err457]; -} -else { -vErrors.push(err457); -} -errors++; -} -if(Array.isArray(data227)){ -const len10 = data227.length; -for(let i10=0; i10<len10; i10++){ -let data228 = data227[i10]; -if(data228 && typeof data228 == "object" && !Array.isArray(data228)){ -if(data228.label === undefined){ -const err458 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err458]; -} -else { -vErrors.push(err458); -} -errors++; -} -for(const key31 in data228){ -if(!((key31 === "label") || (key31 === "selector"))){ -const err459 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key31},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err459]; -} -else { -vErrors.push(err459); -} -errors++; -} -} -if(data228.label !== undefined){ -if(typeof data228.label !== "string"){ -const err460 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10+"/label",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err460]; -} -else { -vErrors.push(err460); -} -errors++; -} -} -if(data228.selector !== undefined){ -if(typeof data228.selector !== "string"){ -const err461 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10+"/selector",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err461]; -} -else { -vErrors.push(err461); -} -errors++; -} -} -} -else { -const err462 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err462]; -} -else { -vErrors.push(err462); -} -errors++; -} -} -} -} -if(data224.element_count !== undefined){ -let data231 = data224.element_count; -if(!((typeof data231 == "number") && (!(data231 % 1) && !isNaN(data231)))){ -const err463 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/element_count",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err463]; -} -else { -vErrors.push(err463); -} -errors++; -} -} -if(data224.page_url !== undefined){ -if(typeof data224.page_url !== "string"){ -const err464 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_url",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err464]; -} -else { -vErrors.push(err464); -} -errors++; -} -} -if(data224.page_title !== undefined){ -if(typeof data224.page_title !== "string"){ -const err465 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_title",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err465]; -} -else { -vErrors.push(err465); -} -errors++; -} -} -} -} -if(data223.text !== undefined){ -if(typeof data223.text !== "string"){ -const err466 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err466]; -} -else { -vErrors.push(err466); -} -errors++; -} -} -if(data223.truncated !== undefined){ -if(typeof data223.truncated !== "boolean"){ -const err467 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/truncated",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err467]; -} -else { -vErrors.push(err467); -} -errors++; -} -} -if(data223.attachments !== undefined){ -let data236 = data223.attachments; -if((data236 !== null) && (!(Array.isArray(data236)))){ -const err468 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err468]; -} -else { -vErrors.push(err468); -} -errors++; -} -if(Array.isArray(data236)){ -const len11 = data236.length; -for(let i11=0; i11<len11; i11++){ -let data237 = data236[i11]; -if(data237 && typeof data237 == "object" && !Array.isArray(data237)){ -if(data237.kind === undefined){ -const err469 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err469]; -} -else { -vErrors.push(err469); -} -errors++; -} -if(data237.content === undefined){ -const err470 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err470]; -} -else { -vErrors.push(err470); -} -errors++; -} -for(const key32 in data237){ -if(!(((key32 === "kind") || (key32 === "name")) || (key32 === "content"))){ -const err471 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key32},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err471]; -} -else { -vErrors.push(err471); -} -errors++; -} -} -if(data237.kind !== undefined){ -if(typeof data237.kind !== "string"){ -const err472 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err472]; -} -else { -vErrors.push(err472); -} -errors++; -} -} -if(data237.name !== undefined){ -if(typeof data237.name !== "string"){ -const err473 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/name",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err473]; -} -else { -vErrors.push(err473); -} -errors++; -} -} -if(data237.content !== undefined){ -let data240 = data237.content; -if(data240 && typeof data240 == "object" && !Array.isArray(data240)){ -if(data240.reference_id === undefined){ -const err474 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err474]; -} -else { -vErrors.push(err474); -} -errors++; -} -if(data240.digest === undefined){ -const err475 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err475]; -} -else { -vErrors.push(err475); -} -errors++; -} -if(data240.size === undefined){ -const err476 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err476]; -} -else { -vErrors.push(err476); -} -errors++; -} -if(data240.media_type === undefined){ -const err477 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err477]; -} -else { -vErrors.push(err477); -} -errors++; -} -if(data240.source === undefined){ -const err478 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err478]; -} -else { -vErrors.push(err478); -} -errors++; -} -for(const key33 in data240){ -if(!((((((((key33 === "inline") || (key33 === "text")) || (key33 === "binary")) || (key33 === "reference_id")) || (key33 === "digest")) || (key33 === "size")) || (key33 === "media_type")) || (key33 === "source"))){ -const err479 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key33},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err479]; -} -else { -vErrors.push(err479); -} -errors++; -} -} -if(data240.text !== undefined){ -let data241 = data240.text; -if((data241 !== null) && (typeof data241 !== "string")){ -const err480 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err480]; -} -else { -vErrors.push(err480); -} -errors++; -} -} -if(data240.binary !== undefined){ -let data242 = data240.binary; -if((typeof data242 !== "string") && (data242 !== null)){ -const err481 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err481]; -} -else { -vErrors.push(err481); -} -errors++; -} -} -if(data240.reference_id !== undefined){ -if(typeof data240.reference_id !== "string"){ -const err482 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err482]; -} -else { -vErrors.push(err482); -} -errors++; -} -} -if(data240.digest !== undefined){ -if(typeof data240.digest !== "string"){ -const err483 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err483]; -} -else { -vErrors.push(err483); -} -errors++; -} -} -if(data240.size !== undefined){ -let data245 = data240.size; -if(typeof data245 === "string"){ -if(!pattern0.test(data245)){ -const err484 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err484]; -} -else { -vErrors.push(err484); -} -errors++; -} -if(!(formats0.validate(data245))){ -const err485 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err485]; -} -else { -vErrors.push(err485); -} -errors++; -} -} -else { -const err486 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err486]; -} -else { -vErrors.push(err486); -} -errors++; -} -} -if(data240.media_type !== undefined){ -if(typeof data240.media_type !== "string"){ -const err487 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err487]; -} -else { -vErrors.push(err487); -} -errors++; -} -} -if(data240.source !== undefined){ -if(typeof data240.source !== "string"){ -const err488 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err488]; -} -else { -vErrors.push(err488); -} -errors++; -} -} -} -else { -const err489 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err489]; -} -else { -vErrors.push(err489); -} -errors++; -} -} -} -else { -const err490 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err490]; -} -else { -vErrors.push(err490); -} -errors++; -} -} -} -} -if(data223.attachment_count !== undefined){ -let data248 = data223.attachment_count; -if(!((typeof data248 == "number") && (!(data248 % 1) && !isNaN(data248)))){ -const err491 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachment_count",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err491]; -} -else { -vErrors.push(err491); -} -errors++; -} -} -} -} -if(data217.root_id !== undefined){ -if(typeof data217.root_id !== "string"){ -const err492 = {instancePath:instancePath+"/items/" + i0+"/inbox/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err492]; -} -else { -vErrors.push(err492); -} -errors++; -} -} -if(data217.agent_id !== undefined){ -if(typeof data217.agent_id !== "string"){ -const err493 = {instancePath:instancePath+"/items/" + i0+"/inbox/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err493]; -} -else { -vErrors.push(err493); -} -errors++; -} -} -if(data217.seq !== undefined){ -let data251 = data217.seq; -if(typeof data251 === "string"){ -if(!pattern0.test(data251)){ -const err494 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err494]; -} -else { -vErrors.push(err494); -} -errors++; -} -if(!(formats0.validate(data251))){ -const err495 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err495]; -} -else { -vErrors.push(err495); -} -errors++; -} -} -else { -const err496 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err496]; -} -else { -vErrors.push(err496); -} -errors++; -} -} -if(data217.kind !== undefined){ -if(typeof data217.kind !== "string"){ -const err497 = {instancePath:instancePath+"/items/" + i0+"/inbox/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err497]; -} -else { -vErrors.push(err497); -} -errors++; -} -} -if(data217.status !== undefined){ -if(typeof data217.status !== "string"){ -const err498 = {instancePath:instancePath+"/items/" + i0+"/inbox/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err498]; -} -else { -vErrors.push(err498); -} -errors++; -} -} -if(data217.payload !== undefined){ -let data254 = data217.payload; -if(data254 && typeof data254 == "object" && !Array.isArray(data254)){ -if(data254.reference_id === undefined){ -const err499 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err499]; -} -else { -vErrors.push(err499); -} -errors++; -} -if(data254.digest === undefined){ -const err500 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err500]; -} -else { -vErrors.push(err500); -} -errors++; -} -if(data254.size === undefined){ -const err501 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err501]; -} -else { -vErrors.push(err501); -} -errors++; -} -if(data254.media_type === undefined){ -const err502 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err502]; -} -else { -vErrors.push(err502); -} -errors++; -} -if(data254.source === undefined){ -const err503 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err503]; -} -else { -vErrors.push(err503); -} -errors++; -} -for(const key34 in data254){ -if(!((((((((key34 === "inline") || (key34 === "text")) || (key34 === "binary")) || (key34 === "reference_id")) || (key34 === "digest")) || (key34 === "size")) || (key34 === "media_type")) || (key34 === "source"))){ -const err504 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key34},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err504]; -} -else { -vErrors.push(err504); -} -errors++; -} -} -if(data254.text !== undefined){ -let data255 = data254.text; -if((data255 !== null) && (typeof data255 !== "string")){ -const err505 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err505]; -} -else { -vErrors.push(err505); -} -errors++; -} -} -if(data254.binary !== undefined){ -let data256 = data254.binary; -if((typeof data256 !== "string") && (data256 !== null)){ -const err506 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err506]; -} -else { -vErrors.push(err506); -} -errors++; -} -} -if(data254.reference_id !== undefined){ -if(typeof data254.reference_id !== "string"){ -const err507 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err507]; -} -else { -vErrors.push(err507); -} -errors++; -} -} -if(data254.digest !== undefined){ -if(typeof data254.digest !== "string"){ -const err508 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err508]; -} -else { -vErrors.push(err508); -} -errors++; -} -} -if(data254.size !== undefined){ -let data259 = data254.size; -if(typeof data259 === "string"){ -if(!pattern0.test(data259)){ -const err509 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err509]; -} -else { -vErrors.push(err509); -} -errors++; -} -if(!(formats0.validate(data259))){ -const err510 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err510]; -} -else { -vErrors.push(err510); -} -errors++; -} -} -else { -const err511 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err511]; -} -else { -vErrors.push(err511); -} -errors++; -} -} -if(data254.media_type !== undefined){ -if(typeof data254.media_type !== "string"){ -const err512 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err512]; -} -else { -vErrors.push(err512); -} -errors++; -} -} -if(data254.source !== undefined){ -if(typeof data254.source !== "string"){ -const err513 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err513]; -} -else { -vErrors.push(err513); -} -errors++; -} -} -} -else { -const err514 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err514]; -} -else { -vErrors.push(err514); -} -errors++; -} -} -} -} -} -else { -const err515 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err515]; -} -else { -vErrors.push(err515); -} -errors++; -} -var _valid0 = _errs467 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 1]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 1; -} -const _errs567 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.blackboard === undefined){ -const err516 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/2/required",keyword:"required",params:{missingProperty: "blackboard"},message:"must have required property '"+"blackboard"+"'"}; -if(vErrors === null){ -vErrors = [err516]; -} -else { -vErrors.push(err516); -} -errors++; -} -for(const key35 in data5){ -if(!(key35 === "blackboard")){ -const err517 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/2/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key35},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err517]; -} -else { -vErrors.push(err517); -} -errors++; -} -} -if(data5.blackboard !== undefined){ -let data262 = data5.blackboard; -if((data262 !== null) && (!(data262 && typeof data262 == "object" && !Array.isArray(data262)))){ -const err518 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err518]; -} -else { -vErrors.push(err518); -} -errors++; -} -if(data262 && typeof data262 == "object" && !Array.isArray(data262)){ -if(data262.key === undefined){ -const err519 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err519]; -} -else { -vErrors.push(err519); -} -errors++; -} -if(data262.version === undefined){ -const err520 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err520]; -} -else { -vErrors.push(err520); -} -errors++; -} -if(data262.author_agent_id === undefined){ -const err521 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err521]; -} -else { -vErrors.push(err521); -} -errors++; -} -if(data262.payload === undefined){ -const err522 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err522]; -} -else { -vErrors.push(err522); -} -errors++; -} -for(const key36 in data262){ -if(!((((key36 === "key") || (key36 === "version")) || (key36 === "author_agent_id")) || (key36 === "payload"))){ -const err523 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key36},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err523]; -} -else { -vErrors.push(err523); -} -errors++; -} -} -if(data262.key !== undefined){ -if(typeof data262.key !== "string"){ -const err524 = {instancePath:instancePath+"/items/" + i0+"/blackboard/key",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err524]; -} -else { -vErrors.push(err524); -} -errors++; -} -} -if(data262.version !== undefined){ -let data264 = data262.version; -if(typeof data264 === "string"){ -if(!pattern0.test(data264)){ -const err525 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err525]; -} -else { -vErrors.push(err525); -} -errors++; -} -if(!(formats0.validate(data264))){ -const err526 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err526]; -} -else { -vErrors.push(err526); -} -errors++; -} -} -else { -const err527 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err527]; -} -else { -vErrors.push(err527); -} -errors++; -} -} -if(data262.author_agent_id !== undefined){ -if(typeof data262.author_agent_id !== "string"){ -const err528 = {instancePath:instancePath+"/items/" + i0+"/blackboard/author_agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err528]; -} -else { -vErrors.push(err528); -} -errors++; -} -} -if(data262.payload !== undefined){ -let data266 = data262.payload; -if(data266 && typeof data266 == "object" && !Array.isArray(data266)){ -if(data266.reference_id === undefined){ -const err529 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err529]; -} -else { -vErrors.push(err529); -} -errors++; -} -if(data266.digest === undefined){ -const err530 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err530]; -} -else { -vErrors.push(err530); -} -errors++; -} -if(data266.size === undefined){ -const err531 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err531]; -} -else { -vErrors.push(err531); -} -errors++; -} -if(data266.media_type === undefined){ -const err532 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err532]; -} -else { -vErrors.push(err532); -} -errors++; -} -if(data266.source === undefined){ -const err533 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err533]; -} -else { -vErrors.push(err533); -} -errors++; -} -for(const key37 in data266){ -if(!((((((((key37 === "inline") || (key37 === "text")) || (key37 === "binary")) || (key37 === "reference_id")) || (key37 === "digest")) || (key37 === "size")) || (key37 === "media_type")) || (key37 === "source"))){ -const err534 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key37},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err534]; -} -else { -vErrors.push(err534); -} -errors++; -} -} -if(data266.text !== undefined){ -let data267 = data266.text; -if((data267 !== null) && (typeof data267 !== "string")){ -const err535 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err535]; -} -else { -vErrors.push(err535); -} -errors++; -} -} -if(data266.binary !== undefined){ -let data268 = data266.binary; -if((typeof data268 !== "string") && (data268 !== null)){ -const err536 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err536]; -} -else { -vErrors.push(err536); -} -errors++; -} -} -if(data266.reference_id !== undefined){ -if(typeof data266.reference_id !== "string"){ -const err537 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err537]; -} -else { -vErrors.push(err537); -} -errors++; -} -} -if(data266.digest !== undefined){ -if(typeof data266.digest !== "string"){ -const err538 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err538]; -} -else { -vErrors.push(err538); -} -errors++; -} -} -if(data266.size !== undefined){ -let data271 = data266.size; -if(typeof data271 === "string"){ -if(!pattern0.test(data271)){ -const err539 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err539]; -} -else { -vErrors.push(err539); -} -errors++; -} -if(!(formats0.validate(data271))){ -const err540 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err540]; -} -else { -vErrors.push(err540); -} -errors++; -} -} -else { -const err541 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err541]; -} -else { -vErrors.push(err541); -} -errors++; -} -} -if(data266.media_type !== undefined){ -if(typeof data266.media_type !== "string"){ -const err542 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err542]; -} -else { -vErrors.push(err542); -} -errors++; -} -} -if(data266.source !== undefined){ -if(typeof data266.source !== "string"){ -const err543 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err543]; -} -else { -vErrors.push(err543); -} -errors++; -} -} -} -else { -const err544 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err544]; -} -else { -vErrors.push(err544); -} -errors++; -} -} -} -} -} -else { -const err545 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/2/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err545]; -} -else { -vErrors.push(err545); -} -errors++; -} -var _valid0 = _errs567 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 2]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 2; -} -const _errs596 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.budget === undefined){ -const err546 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/3/required",keyword:"required",params:{missingProperty: "budget"},message:"must have required property '"+"budget"+"'"}; -if(vErrors === null){ -vErrors = [err546]; -} -else { -vErrors.push(err546); -} -errors++; -} -for(const key38 in data5){ -if(!(key38 === "budget")){ -const err547 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/3/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key38},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err547]; -} -else { -vErrors.push(err547); -} -errors++; -} -} -if(data5.budget !== undefined){ -let data274 = data5.budget; -if((data274 !== null) && (!(data274 && typeof data274 == "object" && !Array.isArray(data274)))){ -const err548 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err548]; -} -else { -vErrors.push(err548); -} -errors++; -} -if(data274 && typeof data274 == "object" && !Array.isArray(data274)){ -if(data274.agent_id === undefined){ -const err549 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err549]; -} -else { -vErrors.push(err549); -} -errors++; -} -if(data274.state === undefined){ -const err550 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err550]; -} -else { -vErrors.push(err550); -} -errors++; -} -for(const key39 in data274){ -if(!((key39 === "agent_id") || (key39 === "state"))){ -const err551 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key39},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err551]; -} -else { -vErrors.push(err551); -} -errors++; -} -} -if(data274.agent_id !== undefined){ -if(typeof data274.agent_id !== "string"){ -const err552 = {instancePath:instancePath+"/items/" + i0+"/budget/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err552]; -} -else { -vErrors.push(err552); -} -errors++; -} -} -if(data274.state !== undefined){ -let data276 = data274.state; -if(data276 && typeof data276 == "object" && !Array.isArray(data276)){ -if(data276.kind === undefined){ -const err553 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err553]; -} -else { -vErrors.push(err553); -} -errors++; -} -if(data276.limit === undefined){ -const err554 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err554]; -} -else { -vErrors.push(err554); -} -errors++; -} -if(data276.used === undefined){ -const err555 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err555]; -} -else { -vErrors.push(err555); -} -errors++; -} -if(data276.reserved === undefined){ -const err556 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err556]; -} -else { -vErrors.push(err556); -} -errors++; -} -if(data276.remaining === undefined){ -const err557 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err557]; -} -else { -vErrors.push(err557); -} -errors++; -} -if(data276.uncertain === undefined){ -const err558 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err558]; -} -else { -vErrors.push(err558); -} -errors++; -} -if(data276.incomplete === undefined){ -const err559 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err559]; -} -else { -vErrors.push(err559); -} -errors++; -} -for(const key40 in data276){ -if(!(((((((key40 === "kind") || (key40 === "limit")) || (key40 === "used")) || (key40 === "reserved")) || (key40 === "remaining")) || (key40 === "uncertain")) || (key40 === "incomplete"))){ -const err560 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key40},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err560]; -} -else { -vErrors.push(err560); -} -errors++; -} -} -if(data276.kind !== undefined){ -if(typeof data276.kind !== "string"){ -const err561 = {instancePath:instancePath+"/items/" + i0+"/budget/state/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err561]; -} -else { -vErrors.push(err561); -} -errors++; -} -} -if(data276.limit !== undefined){ -let data278 = data276.limit; -if((typeof data278 !== "string") && (data278 !== null)){ -const err562 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err562]; -} -else { -vErrors.push(err562); -} -errors++; -} -if(typeof data278 === "string"){ -if(!pattern0.test(data278)){ -const err563 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err563]; -} -else { -vErrors.push(err563); -} -errors++; -} -if(!(formats0.validate(data278))){ -const err564 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err564]; -} -else { -vErrors.push(err564); -} -errors++; -} -} -} -if(data276.used !== undefined){ -let data279 = data276.used; -if(typeof data279 === "string"){ -if(!pattern0.test(data279)){ -const err565 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err565]; -} -else { -vErrors.push(err565); -} -errors++; -} -if(!(formats0.validate(data279))){ -const err566 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err566]; -} -else { -vErrors.push(err566); -} -errors++; -} -} -else { -const err567 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err567]; -} -else { -vErrors.push(err567); -} -errors++; -} -} -if(data276.reserved !== undefined){ -let data280 = data276.reserved; -if(typeof data280 === "string"){ -if(!pattern0.test(data280)){ -const err568 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err568]; -} -else { -vErrors.push(err568); -} -errors++; -} -if(!(formats0.validate(data280))){ -const err569 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err569]; -} -else { -vErrors.push(err569); -} -errors++; -} -} -else { -const err570 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err570]; -} -else { -vErrors.push(err570); -} -errors++; -} -} -if(data276.remaining !== undefined){ -let data281 = data276.remaining; -if((typeof data281 !== "string") && (data281 !== null)){ -const err571 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err571]; -} -else { -vErrors.push(err571); -} -errors++; -} -if(typeof data281 === "string"){ -if(!pattern0.test(data281)){ -const err572 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err572]; -} -else { -vErrors.push(err572); -} -errors++; -} -if(!(formats0.validate(data281))){ -const err573 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err573]; -} -else { -vErrors.push(err573); -} -errors++; -} -} -} -if(data276.uncertain !== undefined){ -let data282 = data276.uncertain; -if(typeof data282 === "string"){ -if(!pattern0.test(data282)){ -const err574 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err574]; -} -else { -vErrors.push(err574); -} -errors++; -} -if(!(formats0.validate(data282))){ -const err575 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err575]; -} -else { -vErrors.push(err575); -} -errors++; -} -} -else { -const err576 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err576]; -} -else { -vErrors.push(err576); -} -errors++; -} -} -if(data276.incomplete !== undefined){ -if(typeof data276.incomplete !== "boolean"){ -const err577 = {instancePath:instancePath+"/items/" + i0+"/budget/state/incomplete",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err577]; -} -else { -vErrors.push(err577); -} -errors++; -} -} -} -else { -const err578 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err578]; -} -else { -vErrors.push(err578); -} -errors++; -} -} -} -} -} -else { -const err579 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/3/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err579]; -} -else { -vErrors.push(err579); -} -errors++; -} -var _valid0 = _errs596 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 3]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 3; -} -const _errs621 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.capability === undefined){ -const err580 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/required",keyword:"required",params:{missingProperty: "capability"},message:"must have required property '"+"capability"+"'"}; -if(vErrors === null){ -vErrors = [err580]; -} -else { -vErrors.push(err580); -} -errors++; -} -for(const key41 in data5){ -if(!(key41 === "capability")){ -const err581 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key41},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err581]; -} -else { -vErrors.push(err581); -} -errors++; -} -} -if(data5.capability !== undefined){ -let data284 = data5.capability; -if((data284 !== null) && (!(data284 && typeof data284 == "object" && !Array.isArray(data284)))){ -const err582 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err582]; -} -else { -vErrors.push(err582); -} -errors++; -} -if(data284 && typeof data284 == "object" && !Array.isArray(data284)){ -if(data284.id === undefined){ -const err583 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err583]; -} -else { -vErrors.push(err583); -} -errors++; -} -if(data284.root_id === undefined){ -const err584 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err584]; -} -else { -vErrors.push(err584); -} -errors++; -} -if(data284.agent_id === undefined){ -const err585 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err585]; -} -else { -vErrors.push(err585); -} -errors++; -} -if(data284.issuer_agent_id === undefined){ -const err586 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err586]; -} -else { -vErrors.push(err586); -} -errors++; -} -if(data284.operations === undefined){ -const err587 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err587]; -} -else { -vErrors.push(err587); -} -errors++; -} -if(data284.scopes === undefined){ -const err588 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err588]; -} -else { -vErrors.push(err588); -} -errors++; -} -if(data284.mcp === undefined){ -const err589 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err589]; -} -else { -vErrors.push(err589); -} -errors++; -} -if(data284.mcp_all === undefined){ -const err590 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err590]; -} -else { -vErrors.push(err590); -} -errors++; -} -if(data284.generation === undefined){ -const err591 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err591]; -} -else { -vErrors.push(err591); -} -errors++; -} -if(data284.status === undefined){ -const err592 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err592]; -} -else { -vErrors.push(err592); -} -errors++; -} -if(data284.expires_at === undefined){ -const err593 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err593]; -} -else { -vErrors.push(err593); -} -errors++; -} -if(data284.created_at === undefined){ -const err594 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err594]; -} -else { -vErrors.push(err594); -} -errors++; -} -if(data284.updated_at === undefined){ -const err595 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err595]; -} -else { -vErrors.push(err595); -} -errors++; -} -for(const key42 in data284){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties, key42))){ -const err596 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key42},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err596]; -} -else { -vErrors.push(err596); -} -errors++; -} -} -if(data284.id !== undefined){ -if(typeof data284.id !== "string"){ -const err597 = {instancePath:instancePath+"/items/" + i0+"/capability/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err597]; -} -else { -vErrors.push(err597); -} -errors++; -} -} -if(data284.root_id !== undefined){ -if(typeof data284.root_id !== "string"){ -const err598 = {instancePath:instancePath+"/items/" + i0+"/capability/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err598]; -} -else { -vErrors.push(err598); -} -errors++; -} -} -if(data284.agent_id !== undefined){ -if(typeof data284.agent_id !== "string"){ -const err599 = {instancePath:instancePath+"/items/" + i0+"/capability/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err599]; -} -else { -vErrors.push(err599); -} -errors++; -} -} -if(data284.issuer_agent_id !== undefined){ -if(typeof data284.issuer_agent_id !== "string"){ -const err600 = {instancePath:instancePath+"/items/" + i0+"/capability/issuer_agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err600]; -} -else { -vErrors.push(err600); -} -errors++; -} -} -if(data284.operations !== undefined){ -let data289 = data284.operations; -if((data289 !== null) && (!(Array.isArray(data289)))){ -const err601 = {instancePath:instancePath+"/items/" + i0+"/capability/operations",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/operations/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err601]; -} -else { -vErrors.push(err601); -} -errors++; -} -if(Array.isArray(data289)){ -const len12 = data289.length; -for(let i12=0; i12<len12; i12++){ -if(typeof data289[i12] !== "string"){ -const err602 = {instancePath:instancePath+"/items/" + i0+"/capability/operations/" + i12,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err602]; -} -else { -vErrors.push(err602); -} -errors++; -} -} -} -} -if(data284.scopes !== undefined){ -let data291 = data284.scopes; -if((data291 !== null) && (!(Array.isArray(data291)))){ -const err603 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/scopes/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err603]; -} -else { -vErrors.push(err603); -} -errors++; -} -if(Array.isArray(data291)){ -const len13 = data291.length; -for(let i13=0; i13<len13; i13++){ -if(typeof data291[i13] !== "string"){ -const err604 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes/" + i13,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err604]; -} -else { -vErrors.push(err604); -} -errors++; -} -} -} -} -if(data284.file_scope !== undefined){ -if(typeof data284.file_scope !== "string"){ -const err605 = {instancePath:instancePath+"/items/" + i0+"/capability/file_scope",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err605]; -} -else { -vErrors.push(err605); -} -errors++; -} -} -if(data284.file_issuer_id !== undefined){ -if(typeof data284.file_issuer_id !== "string"){ -const err606 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err606]; -} -else { -vErrors.push(err606); -} -errors++; -} -} -if(data284.file_issuer_generation !== undefined){ -let data295 = data284.file_issuer_generation; -if(typeof data295 === "string"){ -if(!pattern0.test(data295)){ -const err607 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err607]; -} -else { -vErrors.push(err607); -} -errors++; -} -if(!(formats0.validate(data295))){ -const err608 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err608]; -} -else { -vErrors.push(err608); -} -errors++; -} -} -else { -const err609 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err609]; -} -else { -vErrors.push(err609); -} -errors++; -} -} -if(data284.mcp !== undefined){ -let data296 = data284.mcp; -if((data296 !== null) && (!(Array.isArray(data296)))){ -const err610 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err610]; -} -else { -vErrors.push(err610); -} -errors++; -} -if(Array.isArray(data296)){ -const len14 = data296.length; -for(let i14=0; i14<len14; i14++){ -let data297 = data296[i14]; -if(data297 && typeof data297 == "object" && !Array.isArray(data297)){ -if(data297.server === undefined){ -const err611 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err611]; -} -else { -vErrors.push(err611); -} -errors++; -} -if(data297.tool === undefined){ -const err612 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err612]; -} -else { -vErrors.push(err612); -} -errors++; -} -if(data297.definition === undefined){ -const err613 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err613]; -} -else { -vErrors.push(err613); -} -errors++; -} -for(const key43 in data297){ -if(!(((key43 === "server") || (key43 === "tool")) || (key43 === "definition"))){ -const err614 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key43},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err614]; -} -else { -vErrors.push(err614); -} -errors++; -} -} -if(data297.server !== undefined){ -if(typeof data297.server !== "string"){ -const err615 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/server",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err615]; -} -else { -vErrors.push(err615); -} -errors++; -} -} -if(data297.tool !== undefined){ -if(typeof data297.tool !== "string"){ -const err616 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/tool",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err616]; -} -else { -vErrors.push(err616); -} -errors++; -} -} -if(data297.definition !== undefined){ -if(typeof data297.definition !== "string"){ -const err617 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/definition",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err617]; -} -else { -vErrors.push(err617); -} -errors++; -} -} -} -else { -const err618 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err618]; -} -else { -vErrors.push(err618); -} -errors++; -} -} -} -} -if(data284.mcp_all !== undefined){ -if(typeof data284.mcp_all !== "boolean"){ -const err619 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp_all",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err619]; -} -else { -vErrors.push(err619); -} -errors++; -} -} -if(data284.browser !== undefined){ -let data302 = data284.browser; -if((data302 !== null) && (!(data302 && typeof data302 == "object" && !Array.isArray(data302)))){ -const err620 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err620]; -} -else { -vErrors.push(err620); -} -errors++; -} -if(data302 && typeof data302 == "object" && !Array.isArray(data302)){ -if(data302.provider_id === undefined){ -const err621 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err621]; -} -else { -vErrors.push(err621); -} -errors++; -} -if(data302.provider_epoch === undefined){ -const err622 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err622]; -} -else { -vErrors.push(err622); -} -errors++; -} -if(data302.tab_id === undefined){ -const err623 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err623]; -} -else { -vErrors.push(err623); -} -errors++; -} -if(data302.tab_generation === undefined){ -const err624 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err624]; -} -else { -vErrors.push(err624); -} -errors++; -} -if(data302.profile_id === undefined){ -const err625 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err625]; -} -else { -vErrors.push(err625); -} -errors++; -} -if(data302.rights === undefined){ -const err626 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err626]; -} -else { -vErrors.push(err626); -} -errors++; -} -for(const key44 in data302){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties, key44))){ -const err627 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key44},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err627]; -} -else { -vErrors.push(err627); -} -errors++; -} -} -if(data302.provider_id !== undefined){ -if(typeof data302.provider_id !== "string"){ -const err628 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err628]; -} -else { -vErrors.push(err628); -} -errors++; -} -} -if(data302.provider_epoch !== undefined){ -if(typeof data302.provider_epoch !== "string"){ -const err629 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_epoch",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err629]; -} -else { -vErrors.push(err629); -} -errors++; -} -} -if(data302.tab_id !== undefined){ -if(typeof data302.tab_id !== "string"){ -const err630 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err630]; -} -else { -vErrors.push(err630); -} -errors++; -} -} -if(data302.tab_generation !== undefined){ -if(typeof data302.tab_generation !== "string"){ -const err631 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err631]; -} -else { -vErrors.push(err631); -} -errors++; -} -} -if(data302.profile_id !== undefined){ -if(typeof data302.profile_id !== "string"){ -const err632 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/profile_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err632]; -} -else { -vErrors.push(err632); -} -errors++; -} -} -if(data302.attachment_id !== undefined){ -if(typeof data302.attachment_id !== "string"){ -const err633 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err633]; -} -else { -vErrors.push(err633); -} -errors++; -} -} -if(data302.attachment_generation !== undefined){ -if(typeof data302.attachment_generation !== "string"){ -const err634 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err634]; -} -else { -vErrors.push(err634); -} -errors++; -} -} -if(data302.rights !== undefined){ -let data310 = data302.rights; -if((data310 !== null) && (!(Array.isArray(data310)))){ -const err635 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/rights/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err635]; -} -else { -vErrors.push(err635); -} -errors++; -} -if(Array.isArray(data310)){ -const len15 = data310.length; -for(let i15=0; i15<len15; i15++){ -if(typeof data310[i15] !== "string"){ -const err636 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights/" + i15,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err636]; -} -else { -vErrors.push(err636); -} -errors++; -} -} -} -} -if(data302.preview !== undefined){ -let data312 = data302.preview; -if((data312 !== null) && (!(data312 && typeof data312 == "object" && !Array.isArray(data312)))){ -const err637 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err637]; -} -else { -vErrors.push(err637); -} -errors++; -} -if(data312 && typeof data312 == "object" && !Array.isArray(data312)){ -if(data312.host_id === undefined){ -const err638 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err638]; -} -else { -vErrors.push(err638); -} -errors++; -} -if(data312.host_identity === undefined){ -const err639 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err639]; -} -else { -vErrors.push(err639); -} -errors++; -} -if(data312.connection_generation === undefined){ -const err640 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err640]; -} -else { -vErrors.push(err640); -} -errors++; -} -if(data312.environment_id === undefined){ -const err641 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err641]; -} -else { -vErrors.push(err641); -} -errors++; -} -if(data312.loopback === undefined){ -const err642 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err642]; -} -else { -vErrors.push(err642); -} -errors++; -} -if(data312.ports === undefined){ -const err643 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err643]; -} -else { -vErrors.push(err643); -} -errors++; -} -for(const key45 in data312){ -if(!((((((key45 === "host_id") || (key45 === "host_identity")) || (key45 === "connection_generation")) || (key45 === "environment_id")) || (key45 === "loopback")) || (key45 === "ports"))){ -const err644 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key45},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err644]; -} -else { -vErrors.push(err644); -} -errors++; -} -} -if(data312.host_id !== undefined){ -if(typeof data312.host_id !== "string"){ -const err645 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err645]; -} -else { -vErrors.push(err645); -} -errors++; -} -} -if(data312.host_identity !== undefined){ -if(typeof data312.host_identity !== "string"){ -const err646 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_identity",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err646]; -} -else { -vErrors.push(err646); -} -errors++; -} -} -if(data312.connection_generation !== undefined){ -if(typeof data312.connection_generation !== "string"){ -const err647 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/connection_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err647]; -} -else { -vErrors.push(err647); -} -errors++; -} -} -if(data312.environment_id !== undefined){ -if(typeof data312.environment_id !== "string"){ -const err648 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/environment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err648]; -} -else { -vErrors.push(err648); -} -errors++; -} -} -if(data312.loopback !== undefined){ -if(typeof data312.loopback !== "string"){ -const err649 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/loopback",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err649]; -} -else { -vErrors.push(err649); -} -errors++; -} -} -if(data312.ports !== undefined){ -let data318 = data312.ports; -if((data318 !== null) && (!(Array.isArray(data318)))){ -const err650 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err650]; -} -else { -vErrors.push(err650); -} -errors++; -} -if(Array.isArray(data318)){ -const len16 = data318.length; -for(let i16=0; i16<len16; i16++){ -let data319 = data318[i16]; -if(!((typeof data319 == "number") && (!(data319 % 1) && !isNaN(data319)))){ -const err651 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports/" + i16,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err651]; -} -else { -vErrors.push(err651); -} -errors++; -} -} -} -} -} -} -} -} -if(data284.browser_issuer_id !== undefined){ -if(typeof data284.browser_issuer_id !== "string"){ -const err652 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err652]; -} -else { -vErrors.push(err652); -} -errors++; -} -} -if(data284.browser_issuer_generation !== undefined){ -let data321 = data284.browser_issuer_generation; -if(!((typeof data321 == "number") && (!(data321 % 1) && !isNaN(data321)))){ -const err653 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err653]; -} -else { -vErrors.push(err653); -} -errors++; -} -} -if(data284.browser_delegation_only !== undefined){ -if(typeof data284.browser_delegation_only !== "boolean"){ -const err654 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_delegation_only",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err654]; -} -else { -vErrors.push(err654); -} -errors++; -} -} -if(data284.generation !== undefined){ -let data323 = data284.generation; -if(typeof data323 === "string"){ -if(!pattern0.test(data323)){ -const err655 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err655]; -} -else { -vErrors.push(err655); -} -errors++; -} -if(!(formats0.validate(data323))){ -const err656 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err656]; -} -else { -vErrors.push(err656); -} -errors++; -} -} -else { -const err657 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err657]; -} -else { -vErrors.push(err657); -} -errors++; -} -} -if(data284.status !== undefined){ -if(typeof data284.status !== "string"){ -const err658 = {instancePath:instancePath+"/items/" + i0+"/capability/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err658]; -} -else { -vErrors.push(err658); -} -errors++; -} -} -if(data284.expires_at !== undefined){ -if(typeof data284.expires_at !== "string"){ -const err659 = {instancePath:instancePath+"/items/" + i0+"/capability/expires_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err659]; -} -else { -vErrors.push(err659); -} -errors++; -} -} -if(data284.created_at !== undefined){ -if(typeof data284.created_at !== "string"){ -const err660 = {instancePath:instancePath+"/items/" + i0+"/capability/created_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err660]; -} -else { -vErrors.push(err660); -} -errors++; -} -} -if(data284.updated_at !== undefined){ -if(typeof data284.updated_at !== "string"){ -const err661 = {instancePath:instancePath+"/items/" + i0+"/capability/updated_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err661]; -} -else { -vErrors.push(err661); -} -errors++; -} -} -} -} -} -else { -const err662 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err662]; -} -else { -vErrors.push(err662); -} -errors++; -} -var _valid0 = _errs621 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 4]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 4; -} -const _errs716 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.schedule === undefined){ -const err663 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/5/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err663]; -} -else { -vErrors.push(err663); -} -errors++; -} -for(const key46 in data5){ -if(!(key46 === "schedule")){ -const err664 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/5/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key46},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err664]; -} -else { -vErrors.push(err664); -} -errors++; -} -} -if(data5.schedule !== undefined){ -let data328 = data5.schedule; -if((data328 !== null) && (!(data328 && typeof data328 == "object" && !Array.isArray(data328)))){ -const err665 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[5].properties.schedule.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err665]; -} -else { -vErrors.push(err665); -} -errors++; -} -if(data328 && typeof data328 == "object" && !Array.isArray(data328)){ -if(data328.id === undefined){ -const err666 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err666]; -} -else { -vErrors.push(err666); -} -errors++; -} -if(data328.schedule === undefined){ -const err667 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err667]; -} -else { -vErrors.push(err667); -} -errors++; -} -if(data328.prompt === undefined){ -const err668 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err668]; -} -else { -vErrors.push(err668); -} -errors++; -} -if(data328.anchor === undefined){ -const err669 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err669]; -} -else { -vErrors.push(err669); -} -errors++; -} -if(data328.last_fire === undefined){ -const err670 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err670]; -} -else { -vErrors.push(err670); -} -errors++; -} -for(const key47 in data328){ -if(!(((((key47 === "id") || (key47 === "schedule")) || (key47 === "prompt")) || (key47 === "anchor")) || (key47 === "last_fire"))){ -const err671 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key47},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err671]; -} -else { -vErrors.push(err671); -} -errors++; -} -} -if(data328.id !== undefined){ -let data329 = data328.id; -if(!((typeof data329 == "number") && (!(data329 % 1) && !isNaN(data329)))){ -const err672 = {instancePath:instancePath+"/items/" + i0+"/schedule/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err672]; -} -else { -vErrors.push(err672); -} -errors++; -} -} -if(data328.schedule !== undefined){ -if(typeof data328.schedule !== "string"){ -const err673 = {instancePath:instancePath+"/items/" + i0+"/schedule/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err673]; -} -else { -vErrors.push(err673); -} -errors++; -} -} -if(data328.prompt !== undefined){ -if(typeof data328.prompt !== "string"){ -const err674 = {instancePath:instancePath+"/items/" + i0+"/schedule/prompt",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err674]; -} -else { -vErrors.push(err674); -} -errors++; -} -} -if(data328.anchor !== undefined){ -if(typeof data328.anchor !== "string"){ -const err675 = {instancePath:instancePath+"/items/" + i0+"/schedule/anchor",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err675]; -} -else { -vErrors.push(err675); -} -errors++; -} -} -if(data328.last_fire !== undefined){ -if(typeof data328.last_fire !== "string"){ -const err676 = {instancePath:instancePath+"/items/" + i0+"/schedule/last_fire",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err676]; -} -else { -vErrors.push(err676); -} -errors++; -} -} -} -} -} -else { -const err677 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/5/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err677]; -} -else { -vErrors.push(err677); -} -errors++; -} -var _valid0 = _errs716 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 5]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 5; -} -const _errs732 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.permission === undefined){ -const err678 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/6/required",keyword:"required",params:{missingProperty: "permission"},message:"must have required property '"+"permission"+"'"}; -if(vErrors === null){ -vErrors = [err678]; -} -else { -vErrors.push(err678); -} -errors++; -} -for(const key48 in data5){ -if(!(key48 === "permission")){ -const err679 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/6/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key48},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err679]; -} -else { -vErrors.push(err679); -} -errors++; -} -} -if(data5.permission !== undefined){ -let data334 = data5.permission; -if((data334 !== null) && (!(data334 && typeof data334 == "object" && !Array.isArray(data334)))){ -const err680 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[6].properties.permission.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err680]; -} -else { -vErrors.push(err680); -} -errors++; -} -if(data334 && typeof data334 == "object" && !Array.isArray(data334)){ -if(data334.id === undefined){ -const err681 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err681]; -} -else { -vErrors.push(err681); -} -errors++; -} -if(data334.agent_id === undefined){ -const err682 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err682]; -} -else { -vErrors.push(err682); -} -errors++; -} -if(data334.operation_id === undefined){ -const err683 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err683]; -} -else { -vErrors.push(err683); -} -errors++; -} -if(data334.operation === undefined){ -const err684 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err684]; -} -else { -vErrors.push(err684); -} -errors++; -} -if(data334.canonical_path === undefined){ -const err685 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err685]; -} -else { -vErrors.push(err685); -} -errors++; -} -if(data334.request_digest === undefined){ -const err686 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err686]; -} -else { -vErrors.push(err686); -} -errors++; -} -if(data334.capability_id === undefined){ -const err687 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err687]; -} -else { -vErrors.push(err687); -} -errors++; -} -if(data334.capability_generation === undefined){ -const err688 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err688]; -} -else { -vErrors.push(err688); -} -errors++; -} -if(data334.status === undefined){ -const err689 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err689]; -} -else { -vErrors.push(err689); -} -errors++; -} -if(data334.command === undefined){ -const err690 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err690]; -} -else { -vErrors.push(err690); -} -errors++; -} -if(data334.rule === undefined){ -const err691 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err691]; -} -else { -vErrors.push(err691); -} -errors++; -} -for(const key49 in data334){ -if(!(func2.call(schema156.properties.items.items.allOf[1].oneOf[6].properties.permission.properties, key49))){ -const err692 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key49},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err692]; -} -else { -vErrors.push(err692); -} -errors++; -} -} -if(data334.id !== undefined){ -if(typeof data334.id !== "string"){ -const err693 = {instancePath:instancePath+"/items/" + i0+"/permission/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err693]; -} -else { -vErrors.push(err693); -} -errors++; -} -} -if(data334.agent_id !== undefined){ -if(typeof data334.agent_id !== "string"){ -const err694 = {instancePath:instancePath+"/items/" + i0+"/permission/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err694]; -} -else { -vErrors.push(err694); -} -errors++; -} -} -if(data334.operation_id !== undefined){ -if(typeof data334.operation_id !== "string"){ -const err695 = {instancePath:instancePath+"/items/" + i0+"/permission/operation_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err695]; -} -else { -vErrors.push(err695); -} -errors++; -} -} -if(data334.operation !== undefined){ -if(typeof data334.operation !== "string"){ -const err696 = {instancePath:instancePath+"/items/" + i0+"/permission/operation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err696]; -} -else { -vErrors.push(err696); -} -errors++; -} -} -if(data334.canonical_path !== undefined){ -if(typeof data334.canonical_path !== "string"){ -const err697 = {instancePath:instancePath+"/items/" + i0+"/permission/canonical_path",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err697]; -} -else { -vErrors.push(err697); -} -errors++; -} -} -if(data334.request_digest !== undefined){ -if(typeof data334.request_digest !== "string"){ -const err698 = {instancePath:instancePath+"/items/" + i0+"/permission/request_digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err698]; -} -else { -vErrors.push(err698); -} -errors++; -} -} -if(data334.capability_id !== undefined){ -if(typeof data334.capability_id !== "string"){ -const err699 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err699]; -} -else { -vErrors.push(err699); -} -errors++; -} -} -if(data334.capability_generation !== undefined){ -let data342 = data334.capability_generation; -if(typeof data342 === "string"){ -if(!pattern0.test(data342)){ -const err700 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err700]; -} -else { -vErrors.push(err700); -} -errors++; -} -if(!(formats0.validate(data342))){ -const err701 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err701]; -} -else { -vErrors.push(err701); -} -errors++; -} -} -else { -const err702 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err702]; -} -else { -vErrors.push(err702); -} -errors++; -} -} -if(data334.status !== undefined){ -if(typeof data334.status !== "string"){ -const err703 = {instancePath:instancePath+"/items/" + i0+"/permission/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err703]; -} -else { -vErrors.push(err703); -} -errors++; -} -} -if(data334.command !== undefined){ -if(typeof data334.command !== "string"){ -const err704 = {instancePath:instancePath+"/items/" + i0+"/permission/command",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err704]; -} -else { -vErrors.push(err704); -} -errors++; -} -} -if(data334.rule !== undefined){ -if(typeof data334.rule !== "string"){ -const err705 = {instancePath:instancePath+"/items/" + i0+"/permission/rule",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err705]; -} -else { -vErrors.push(err705); -} -errors++; -} -} -} -} -} -else { -const err706 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/6/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err706]; -} -else { -vErrors.push(err706); -} -errors++; -} -var _valid0 = _errs732 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 6]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 6; -} -const _errs760 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.body === undefined){ -const err707 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/7/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err707]; -} -else { -vErrors.push(err707); -} -errors++; -} -for(const key50 in data5){ -if(!(key50 === "body")){ -const err708 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/7/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key50},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err708]; -} -else { -vErrors.push(err708); -} -errors++; -} -} -if(data5.body !== undefined){ -let data346 = data5.body; -if((data346 !== null) && (!(data346 && typeof data346 == "object" && !Array.isArray(data346)))){ -const err709 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err709]; -} -else { -vErrors.push(err709); -} -errors++; -} -if(data346 && typeof data346 == "object" && !Array.isArray(data346)){ -if(data346.reference_id === undefined){ -const err710 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err710]; -} -else { -vErrors.push(err710); -} -errors++; -} -if(data346.digest === undefined){ -const err711 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err711]; -} -else { -vErrors.push(err711); -} -errors++; -} -if(data346.size === undefined){ -const err712 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err712]; -} -else { -vErrors.push(err712); -} -errors++; -} -if(data346.media_type === undefined){ -const err713 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err713]; -} -else { -vErrors.push(err713); -} -errors++; -} -if(data346.source === undefined){ -const err714 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err714]; -} -else { -vErrors.push(err714); -} -errors++; -} -for(const key51 in data346){ -if(!((((((((key51 === "inline") || (key51 === "text")) || (key51 === "binary")) || (key51 === "reference_id")) || (key51 === "digest")) || (key51 === "size")) || (key51 === "media_type")) || (key51 === "source"))){ -const err715 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key51},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err715]; -} -else { -vErrors.push(err715); -} -errors++; -} -} -if(data346.text !== undefined){ -let data347 = data346.text; -if((data347 !== null) && (typeof data347 !== "string")){ -const err716 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err716]; -} -else { -vErrors.push(err716); -} -errors++; -} -} -if(data346.binary !== undefined){ -let data348 = data346.binary; -if((typeof data348 !== "string") && (data348 !== null)){ -const err717 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err717]; -} -else { -vErrors.push(err717); -} -errors++; -} -} -if(data346.reference_id !== undefined){ -if(typeof data346.reference_id !== "string"){ -const err718 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err718]; -} -else { -vErrors.push(err718); -} -errors++; -} -} -if(data346.digest !== undefined){ -if(typeof data346.digest !== "string"){ -const err719 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err719]; -} -else { -vErrors.push(err719); -} -errors++; -} -} -if(data346.size !== undefined){ -let data351 = data346.size; -if(typeof data351 === "string"){ -if(!pattern0.test(data351)){ -const err720 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err720]; -} -else { -vErrors.push(err720); -} -errors++; -} -if(!(formats0.validate(data351))){ -const err721 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err721]; -} -else { -vErrors.push(err721); -} -errors++; -} -} -else { -const err722 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err722]; -} -else { -vErrors.push(err722); -} -errors++; -} -} -if(data346.media_type !== undefined){ -if(typeof data346.media_type !== "string"){ -const err723 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err723]; -} -else { -vErrors.push(err723); -} -errors++; -} -} -if(data346.source !== undefined){ -if(typeof data346.source !== "string"){ -const err724 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err724]; -} -else { -vErrors.push(err724); -} -errors++; -} -} -} -} -} -else { -const err725 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/7/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err725]; -} -else { -vErrors.push(err725); -} -errors++; -} -var _valid0 = _errs760 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 7]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 7; -} -} -} -} -} -} -} -} -if(!valid42){ -const err726 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"}; -if(vErrors === null){ -vErrors = [err726]; -} -else { -vErrors.push(err726); -} -errors++; -} -else { -errors = _errs386; -if(vErrors !== null){ -if(_errs386){ -vErrors.length = _errs386; -} -else { -vErrors = null; -} -} -} -} -} -} -if(data.next_cursor !== undefined){ -let data354 = data.next_cursor; -if((data354 !== null) && (!(data354 && typeof data354 == "object" && !Array.isArray(data354)))){ -const err727 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema156.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err727]; -} -else { -vErrors.push(err727); -} -errors++; -} -if(data354 && typeof data354 == "object" && !Array.isArray(data354)){ -if(data354.root_id === undefined){ -const err728 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err728]; -} -else { -vErrors.push(err728); -} -errors++; -} -if(data354.collection === undefined){ -const err729 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err729]; -} -else { -vErrors.push(err729); -} -errors++; -} -if(data354.revision === undefined){ -const err730 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err730]; -} -else { -vErrors.push(err730); -} -errors++; -} -if(data354.offset === undefined){ -const err731 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err731]; -} -else { -vErrors.push(err731); -} -errors++; -} -for(const key52 in data354){ -if(!((((key52 === "root_id") || (key52 === "collection")) || (key52 === "revision")) || (key52 === "offset"))){ -const err732 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key52},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err732]; -} -else { -vErrors.push(err732); -} -errors++; -} -} -if(data354.root_id !== undefined){ -if(typeof data354.root_id !== "string"){ -const err733 = {instancePath:instancePath+"/next_cursor/root_id",schemaPath:"#/properties/next_cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err733]; -} -else { -vErrors.push(err733); -} -errors++; -} -} -if(data354.collection !== undefined){ -if(typeof data354.collection !== "string"){ -const err734 = {instancePath:instancePath+"/next_cursor/collection",schemaPath:"#/properties/next_cursor/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err734]; -} -else { -vErrors.push(err734); -} -errors++; -} -} -if(data354.revision !== undefined){ -let data357 = data354.revision; -if(typeof data357 === "string"){ -if(!pattern0.test(data357)){ -const err735 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err735]; -} -else { -vErrors.push(err735); -} -errors++; -} -if(!(formats0.validate(data357))){ -const err736 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err736]; -} -else { -vErrors.push(err736); -} -errors++; -} -} -else { -const err737 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err737]; -} -else { -vErrors.push(err737); -} -errors++; -} -} -if(data354.offset !== undefined){ -let data358 = data354.offset; -if(typeof data358 === "string"){ -if(!pattern0.test(data358)){ -const err738 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err738]; -} -else { -vErrors.push(err738); -} -errors++; -} -if(!(formats0.validate(data358))){ -const err739 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err739]; -} -else { -vErrors.push(err739); -} -errors++; -} -} -else { -const err740 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err740]; -} -else { -vErrors.push(err740); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err741 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err741]; -} -else { -vErrors.push(err741); -} -errors++; -} -} -} -else { -const err742 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err742]; -} -else { -vErrors.push(err742); -} -errors++; -} -validate155.errors = vErrors; -return errors === 0; -} - -export const RootCollectionParams = validate156; -const schema157 = {"type":"object","properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","collection","revision","offset"],"additionalProperties":false},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RootCollectionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RootCollectionParams","required":["root_id","collection","limit","max_bytes"],"additionalProperties":false}; - -function validate156(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootCollectionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.collection === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.max_bytes === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "collection")) || (key0 === "cursor")) || (key0 === "limit")) || (key0 === "max_bytes"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.collection !== undefined){ -if(typeof data.collection !== "string"){ -const err6 = {instancePath:instancePath+"/collection",schemaPath:"#/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema157.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.root_id === undefined){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.collection === undefined){ -const err9 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.revision === undefined){ -const err10 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.offset === undefined){ -const err11 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -for(const key1 in data2){ -if(!((((key1 === "root_id") || (key1 === "collection")) || (key1 === "revision")) || (key1 === "offset"))){ -const err12 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data2.root_id !== undefined){ -if(typeof data2.root_id !== "string"){ -const err13 = {instancePath:instancePath+"/cursor/root_id",schemaPath:"#/properties/cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data2.collection !== undefined){ -if(typeof data2.collection !== "string"){ -const err14 = {instancePath:instancePath+"/cursor/collection",schemaPath:"#/properties/cursor/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data2.revision !== undefined){ -let data5 = data2.revision; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err15 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err16 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data2.offset !== undefined){ -let data6 = data2.offset; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err18 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err19 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -else { -const err20 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data7 = data.limit; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err21 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data8 = data.max_bytes; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err22 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -validate156.errors = vErrors; -return errors === 0; -} - -export const RootIDResult = validate157; -const schema158 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootIDResult","$schema":"http://json-schema.org/draft-07/schema#","title":"RootIDResult","required":["root_id"],"additionalProperties":false}; - -function validate157(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootIDResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "root_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate157.errors = vErrors; -return errors === 0; -} - -export const RootParams = validate158; -const schema159 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RootParams","required":["root_id"],"additionalProperties":false}; - -function validate158(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "root_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate158.errors = vErrors; -return errors === 0; -} - -export const RootSnapshot = validate159; -const schema160 = {"type":"object","properties":{"collection_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"active_turns":{"type":"object","additionalProperties":{"type":"string"}},"omitted":{"type":"object","additionalProperties":{"type":"boolean"}},"message_seqs":{"type":["null","array"],"items":{"type":"integer"}},"first_message_seq":{"type":"integer"},"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"meta":{"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"definition_revision":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"goal":{"type":"string"},"forked_from":{"type":"string"},"fork_seq":{"type":"integer"},"tags":{"type":["null","array"],"items":{"type":"string"}},"archived":{"type":"boolean"},"pinned":{"type":"boolean"},"effort":{"type":"string"},"usage_in":{"type":"integer"},"usage_cached":{"type":"integer"},"usage_out":{"type":"integer"},"updated_at":{"type":"string"}},"required":["execution_engine","definition","definition_revision","id","kind","title","model","provider","cwd","goal","forked_from","fork_seq","tags","archived","pinned","effort","usage_in","usage_cached","usage_out","updated_at"],"additionalProperties":false},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":false},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false}},"required":["invocation_id","name","status"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":false}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":false},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":false},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":false}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":false}},"presentation":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":false}},"agent_presentations":{"type":"object","additionalProperties":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":false}}},"agents":{"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":false},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":false}},"inbox":{"type":["null","array"],"items":{"type":"object","properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["kind","content"],"additionalProperties":false}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":false},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":false}},"blackboard":{"type":["null","array"],"items":{"type":"object","properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":false}},"required":["key","version","author_agent_id","payload"],"additionalProperties":false}},"budgets":{"type":["null","array"],"items":{"type":"object","properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":false}},"required":["agent_id","state"],"additionalProperties":false}},"accounting":{"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"capabilities":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":false}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":false}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":false},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":false}},"schedules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":false}},"upcoming_schedules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"next_fire":{"type":"string"},"prompt":{"type":"string"},"prompt_truncated":{"type":"boolean"}},"required":["id","next_fire","prompt"],"additionalProperties":false}},"upcoming_schedule_count":{"type":["null","integer"]},"permissions":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":false}},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":false},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":false}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":false}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":false}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":false}}},"additionalProperties":false}},"permission_mode":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootSnapshot","$schema":"http://json-schema.org/draft-07/schema#","title":"RootSnapshot","required":["active_turns","message_seqs","history_revision","root_id","cursor","meta","messages","presentation","agent_presentations","agents","inbox","blackboard","budgets","capabilities","schedules","permissions","questions"],"additionalProperties":false}; - -function validate159(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootSnapshot" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.active_turns === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "active_turns"},message:"must have required property '"+"active_turns"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.message_seqs === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "message_seqs"},message:"must have required property '"+"message_seqs"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.history_revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.root_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.cursor === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.meta === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "meta"},message:"must have required property '"+"meta"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.messages === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.presentation === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "presentation"},message:"must have required property '"+"presentation"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.agent_presentations === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_presentations"},message:"must have required property '"+"agent_presentations"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.agents === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agents"},message:"must have required property '"+"agents"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.inbox === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox"},message:"must have required property '"+"inbox"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.blackboard === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "blackboard"},message:"must have required property '"+"blackboard"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.budgets === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.capabilities === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data.schedules === undefined){ -const err14 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedules"},message:"must have required property '"+"schedules"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data.permissions === undefined){ -const err15 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permissions"},message:"must have required property '"+"permissions"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data.questions === undefined){ -const err16 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "questions"},message:"must have required property '"+"questions"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema160.properties, key0))){ -const err17 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.collection_revision !== undefined){ -let data0 = data.collection_revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err18 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err19 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -else { -const err20 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.active_turns !== undefined){ -let data1 = data.active_turns; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key1 in data1){ -if(typeof data1[key1] !== "string"){ -const err21 = {instancePath:instancePath+"/active_turns/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/active_turns/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -else { -const err22 = {instancePath:instancePath+"/active_turns",schemaPath:"#/properties/active_turns/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.omitted !== undefined){ -let data3 = data.omitted; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -for(const key2 in data3){ -if(typeof data3[key2] !== "boolean"){ -const err23 = {instancePath:instancePath+"/omitted/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/omitted/additionalProperties/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath:instancePath+"/omitted",schemaPath:"#/properties/omitted/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.message_seqs !== undefined){ -let data5 = data.message_seqs; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err25 = {instancePath:instancePath+"/message_seqs",schemaPath:"#/properties/message_seqs/type",keyword:"type",params:{type: schema160.properties.message_seqs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -let data6 = data5[i0]; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err26 = {instancePath:instancePath+"/message_seqs/" + i0,schemaPath:"#/properties/message_seqs/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -} -if(data.first_message_seq !== undefined){ -let data7 = data.first_message_seq; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err27 = {instancePath:instancePath+"/first_message_seq",schemaPath:"#/properties/first_message_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.history_revision !== undefined){ -let data8 = data.history_revision; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err28 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err29 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -else { -const err30 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err31 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data10 = data.cursor; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err32 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err33 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -else { -const err34 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data.meta !== undefined){ -let data11 = data.meta; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.execution_engine === undefined){ -const err35 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data11.definition === undefined){ -const err36 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data11.definition_revision === undefined){ -const err37 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "definition_revision"},message:"must have required property '"+"definition_revision"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data11.id === undefined){ -const err38 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data11.kind === undefined){ -const err39 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data11.title === undefined){ -const err40 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data11.model === undefined){ -const err41 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data11.provider === undefined){ -const err42 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data11.cwd === undefined){ -const err43 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data11.goal === undefined){ -const err44 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data11.forked_from === undefined){ -const err45 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "forked_from"},message:"must have required property '"+"forked_from"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data11.fork_seq === undefined){ -const err46 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "fork_seq"},message:"must have required property '"+"fork_seq"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data11.tags === undefined){ -const err47 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "tags"},message:"must have required property '"+"tags"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data11.archived === undefined){ -const err48 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data11.pinned === undefined){ -const err49 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data11.effort === undefined){ -const err50 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data11.usage_in === undefined){ -const err51 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_in"},message:"must have required property '"+"usage_in"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data11.usage_cached === undefined){ -const err52 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_cached"},message:"must have required property '"+"usage_cached"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data11.usage_out === undefined){ -const err53 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_out"},message:"must have required property '"+"usage_out"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data11.updated_at === undefined){ -const err54 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -for(const key3 in data11){ -if(!(func2.call(schema160.properties.meta.properties, key3))){ -const err55 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data11.execution_engine !== undefined){ -if(typeof data11.execution_engine !== "string"){ -const err56 = {instancePath:instancePath+"/meta/execution_engine",schemaPath:"#/properties/meta/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data11.definition !== undefined){ -if(typeof data11.definition !== "string"){ -const err57 = {instancePath:instancePath+"/meta/definition",schemaPath:"#/properties/meta/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data11.definition_revision !== undefined){ -if(typeof data11.definition_revision !== "string"){ -const err58 = {instancePath:instancePath+"/meta/definition_revision",schemaPath:"#/properties/meta/properties/definition_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data11.id !== undefined){ -if(typeof data11.id !== "string"){ -const err59 = {instancePath:instancePath+"/meta/id",schemaPath:"#/properties/meta/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data11.kind !== undefined){ -if(typeof data11.kind !== "string"){ -const err60 = {instancePath:instancePath+"/meta/kind",schemaPath:"#/properties/meta/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data11.title !== undefined){ -if(typeof data11.title !== "string"){ -const err61 = {instancePath:instancePath+"/meta/title",schemaPath:"#/properties/meta/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data11.model !== undefined){ -if(typeof data11.model !== "string"){ -const err62 = {instancePath:instancePath+"/meta/model",schemaPath:"#/properties/meta/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data11.provider !== undefined){ -if(typeof data11.provider !== "string"){ -const err63 = {instancePath:instancePath+"/meta/provider",schemaPath:"#/properties/meta/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data11.cwd !== undefined){ -if(typeof data11.cwd !== "string"){ -const err64 = {instancePath:instancePath+"/meta/cwd",schemaPath:"#/properties/meta/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data11.goal !== undefined){ -if(typeof data11.goal !== "string"){ -const err65 = {instancePath:instancePath+"/meta/goal",schemaPath:"#/properties/meta/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data11.forked_from !== undefined){ -if(typeof data11.forked_from !== "string"){ -const err66 = {instancePath:instancePath+"/meta/forked_from",schemaPath:"#/properties/meta/properties/forked_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data11.fork_seq !== undefined){ -let data23 = data11.fork_seq; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err67 = {instancePath:instancePath+"/meta/fork_seq",schemaPath:"#/properties/meta/properties/fork_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data11.tags !== undefined){ -let data24 = data11.tags; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err68 = {instancePath:instancePath+"/meta/tags",schemaPath:"#/properties/meta/properties/tags/type",keyword:"type",params:{type: schema160.properties.meta.properties.tags.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(Array.isArray(data24)){ -const len1 = data24.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data24[i1] !== "string"){ -const err69 = {instancePath:instancePath+"/meta/tags/" + i1,schemaPath:"#/properties/meta/properties/tags/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -} -if(data11.archived !== undefined){ -if(typeof data11.archived !== "boolean"){ -const err70 = {instancePath:instancePath+"/meta/archived",schemaPath:"#/properties/meta/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data11.pinned !== undefined){ -if(typeof data11.pinned !== "boolean"){ -const err71 = {instancePath:instancePath+"/meta/pinned",schemaPath:"#/properties/meta/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data11.effort !== undefined){ -if(typeof data11.effort !== "string"){ -const err72 = {instancePath:instancePath+"/meta/effort",schemaPath:"#/properties/meta/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data11.usage_in !== undefined){ -let data29 = data11.usage_in; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err73 = {instancePath:instancePath+"/meta/usage_in",schemaPath:"#/properties/meta/properties/usage_in/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data11.usage_cached !== undefined){ -let data30 = data11.usage_cached; -if(!((typeof data30 == "number") && (!(data30 % 1) && !isNaN(data30)))){ -const err74 = {instancePath:instancePath+"/meta/usage_cached",schemaPath:"#/properties/meta/properties/usage_cached/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data11.usage_out !== undefined){ -let data31 = data11.usage_out; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err75 = {instancePath:instancePath+"/meta/usage_out",schemaPath:"#/properties/meta/properties/usage_out/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data11.updated_at !== undefined){ -if(typeof data11.updated_at !== "string"){ -const err76 = {instancePath:instancePath+"/meta/updated_at",schemaPath:"#/properties/meta/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -} -else { -const err77 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.messages !== undefined){ -let data33 = data.messages; -if((data33 !== null) && (!(Array.isArray(data33)))){ -const err78 = {instancePath:instancePath+"/messages",schemaPath:"#/properties/messages/type",keyword:"type",params:{type: schema160.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(Array.isArray(data33)){ -const len2 = data33.length; -for(let i2=0; i2<len2; i2++){ -let data34 = data33[i2]; -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -if(data34.role === undefined){ -const err79 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data34.content === undefined){ -const err80 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -for(const key4 in data34){ -if(!(func2.call(schema160.properties.messages.items.properties, key4))){ -const err81 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data34.presentation !== undefined){ -let data35 = data34.presentation; -if((data35 !== null) && (!(data35 && typeof data35 == "object" && !Array.isArray(data35)))){ -const err82 = {instancePath:instancePath+"/messages/" + i2+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data35 && typeof data35 == "object" && !Array.isArray(data35)){ -if(data35.version === undefined){ -const err83 = {instancePath:instancePath+"/messages/" + i2+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -for(const key5 in data35){ -if(!(((((key5 === "design_context") || (key5 === "version")) || (key5 === "turn_id")) || (key5 === "parts")) || (key5 === "omitted"))){ -const err84 = {instancePath:instancePath+"/messages/" + i2+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data35.design_context !== undefined){ -let data36 = data35.design_context; -if((data36 !== null) && (!(data36 && typeof data36 == "object" && !Array.isArray(data36)))){ -const err85 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data36 && typeof data36 == "object" && !Array.isArray(data36)){ -if(data36.context_attachment_id === undefined){ -const err86 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data36.elements === undefined){ -const err87 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -if(data36.element_count === undefined){ -const err88 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(data36.context_part_index === undefined){ -const err89 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -for(const key6 in data36){ -if(!((((((((key6 === "context_attachment_id") || (key6 === "screenshot_attachment_id")) || (key6 === "elements")) || (key6 === "element_count")) || (key6 === "page_url")) || (key6 === "page_title")) || (key6 === "context_part_index")) || (key6 === "screenshot_part_index"))){ -const err90 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data36.context_attachment_id !== undefined){ -if(typeof data36.context_attachment_id !== "string"){ -const err91 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data36.screenshot_attachment_id !== undefined){ -if(typeof data36.screenshot_attachment_id !== "string"){ -const err92 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data36.elements !== undefined){ -let data39 = data36.elements; -if((data39 !== null) && (!(Array.isArray(data39)))){ -const err93 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(Array.isArray(data39)){ -const len3 = data39.length; -for(let i3=0; i3<len3; i3++){ -let data40 = data39[i3]; -if(data40 && typeof data40 == "object" && !Array.isArray(data40)){ -if(data40.label === undefined){ -const err94 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -for(const key7 in data40){ -if(!((key7 === "label") || (key7 === "selector"))){ -const err95 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key7},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data40.label !== undefined){ -if(typeof data40.label !== "string"){ -const err96 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3+"/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data40.selector !== undefined){ -if(typeof data40.selector !== "string"){ -const err97 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3+"/selector",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -else { -const err98 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -} -if(data36.element_count !== undefined){ -let data43 = data36.element_count; -if(!((typeof data43 == "number") && (!(data43 % 1) && !isNaN(data43)))){ -const err99 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data36.page_url !== undefined){ -if(typeof data36.page_url !== "string"){ -const err100 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data36.page_title !== undefined){ -if(typeof data36.page_title !== "string"){ -const err101 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data36.context_part_index !== undefined){ -let data46 = data36.context_part_index; -if(!((typeof data46 == "number") && (!(data46 % 1) && !isNaN(data46)))){ -const err102 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data36.screenshot_part_index !== undefined){ -let data47 = data36.screenshot_part_index; -if((data47 !== null) && (!((typeof data47 == "number") && (!(data47 % 1) && !isNaN(data47))))){ -const err103 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -} -} -if(data35.version !== undefined){ -let data48 = data35.version; -if(!((typeof data48 == "number") && (!(data48 % 1) && !isNaN(data48)))){ -const err104 = {instancePath:instancePath+"/messages/" + i2+"/presentation/version",schemaPath:"#/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data35.turn_id !== undefined){ -if(typeof data35.turn_id !== "string"){ -const err105 = {instancePath:instancePath+"/messages/" + i2+"/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data35.parts !== undefined){ -let data50 = data35.parts; -if((data50 !== null) && (!(Array.isArray(data50)))){ -const err106 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(Array.isArray(data50)){ -const len4 = data50.length; -for(let i4=0; i4<len4; i4++){ -let data51 = data50[i4]; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.id === undefined){ -const err107 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -if(data51.kind === undefined){ -const err108 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -for(const key8 in data51){ -if(!(func2.call(schema160.properties.messages.items.properties.presentation.properties.parts.items.properties, key8))){ -const err109 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key8},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data51.id !== undefined){ -if(typeof data51.id !== "string"){ -const err110 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data51.kind !== undefined){ -if(typeof data51.kind !== "string"){ -const err111 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/kind",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data51.start !== undefined){ -let data54 = data51.start; -if(!((typeof data54 == "number") && (!(data54 % 1) && !isNaN(data54)))){ -const err112 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/start",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data51.end !== undefined){ -let data55 = data51.end; -if(!((typeof data55 == "number") && (!(data55 % 1) && !isNaN(data55)))){ -const err113 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/end",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data51.text !== undefined){ -if(typeof data51.text !== "string"){ -const err114 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/text",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data51.tool_name !== undefined){ -if(typeof data51.tool_name !== "string"){ -const err115 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/tool_name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data51.status !== undefined){ -if(typeof data51.status !== "string"){ -const err116 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data51.call_id !== undefined){ -if(typeof data51.call_id !== "string"){ -const err117 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/call_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -if(data51.hosts !== undefined){ -let data60 = data51.hosts; -if((data60 !== null) && (!(Array.isArray(data60)))){ -const err118 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(Array.isArray(data60)){ -const len5 = data60.length; -for(let i5=0; i5<len5; i5++){ -let data61 = data60[i5]; -if(data61 && typeof data61 == "object" && !Array.isArray(data61)){ -if(data61.invocation_id === undefined){ -const err119 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data61.name === undefined){ -const err120 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(data61.status === undefined){ -const err121 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -for(const key9 in data61){ -if(!(((((((key9 === "invocation_id") || (key9 === "name")) || (key9 === "summary")) || (key9 === "status")) || (key9 === "duration")) || (key9 === "error")) || (key9 === "display"))){ -const err122 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key9},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data61.invocation_id !== undefined){ -if(typeof data61.invocation_id !== "string"){ -const err123 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/invocation_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data61.name !== undefined){ -if(typeof data61.name !== "string"){ -const err124 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data61.summary !== undefined){ -if(typeof data61.summary !== "string"){ -const err125 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/summary",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data61.status !== undefined){ -if(typeof data61.status !== "string"){ -const err126 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -if(data61.duration !== undefined){ -if(typeof data61.duration !== "string"){ -const err127 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/duration",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data61.error !== undefined){ -if(typeof data61.error !== "string"){ -const err128 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/error",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data61.display !== undefined){ -let data68 = data61.display; -if((data68 !== null) && (!(data68 && typeof data68 == "object" && !Array.isArray(data68)))){ -const err129 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -for(const key10 in data68){ -if(!(((((key10 === "target") || (key10 === "command")) || (key10 === "query")) || (key10 === "child_id")) || (key10 === "label"))){ -const err130 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key10},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -if(data68.target !== undefined){ -if(typeof data68.target !== "string"){ -const err131 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/target",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -if(data68.command !== undefined){ -if(typeof data68.command !== "string"){ -const err132 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/command",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data68.query !== undefined){ -if(typeof data68.query !== "string"){ -const err133 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/query",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data68.child_id !== undefined){ -if(typeof data68.child_id !== "string"){ -const err134 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/child_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data68.label !== undefined){ -if(typeof data68.label !== "string"){ -const err135 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -} -} -} -else { -const err136 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -} -} -if(data51.omitted !== undefined){ -let data74 = data51.omitted; -if(!((typeof data74 == "number") && (!(data74 % 1) && !isNaN(data74)))){ -const err137 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -} -else { -const err138 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -if(data35.omitted !== undefined){ -let data75 = data35.omitted; -if(!((typeof data75 == "number") && (!(data75 % 1) && !isNaN(data75)))){ -const err139 = {instancePath:instancePath+"/messages/" + i2+"/presentation/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -} -} -if(data34.role !== undefined){ -if(typeof data34.role !== "string"){ -const err140 = {instancePath:instancePath+"/messages/" + i2+"/role",schemaPath:"#/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -if(data34.content !== undefined){ -let data77 = data34.content; -const _errs167 = errors; -let valid23 = false; -const _errs168 = errors; -if(typeof data77 !== "string"){ -const err141 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -var _valid0 = _errs168 === errors; -valid23 = valid23 || _valid0; -if(!valid23){ -const _errs170 = errors; -if(Array.isArray(data77)){ -const len6 = data77.length; -for(let i6=0; i6<len6; i6++){ -let data78 = data77[i6]; -if(data78 && typeof data78 == "object" && !Array.isArray(data78)){ -if(data78.type === undefined){ -const err142 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6,schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -for(const key11 in data78){ -if(!(((((key11 === "type") || (key11 === "text")) || (key11 === "image_url")) || (key11 === "w")) || (key11 === "h"))){ -const err143 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6,schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key11},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data78.type !== undefined){ -if(typeof data78.type !== "string"){ -const err144 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/type",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -if(data78.text !== undefined){ -if(typeof data78.text !== "string"){ -const err145 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/text",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -if(data78.image_url !== undefined){ -let data81 = data78.image_url; -if((data81 !== null) && (!(data81 && typeof data81 == "object" && !Array.isArray(data81)))){ -const err146 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -if(data81 && typeof data81 == "object" && !Array.isArray(data81)){ -if(data81.url === undefined){ -const err147 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -for(const key12 in data81){ -if(!(key12 === "url")){ -const err148 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key12},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data81.url !== undefined){ -if(typeof data81.url !== "string"){ -const err149 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url/url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -} -} -if(data78.w !== undefined){ -let data83 = data78.w; -if(!((typeof data83 == "number") && (!(data83 % 1) && !isNaN(data83)))){ -const err150 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/w",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -if(data78.h !== undefined){ -let data84 = data78.h; -if(!((typeof data84 == "number") && (!(data84 % 1) && !isNaN(data84)))){ -const err151 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/h",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -} -else { -const err152 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6,schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -} -else { -const err153 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -var _valid0 = _errs170 === errors; -valid23 = valid23 || _valid0; -} -if(!valid23){ -const err154 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -else { -errors = _errs167; -if(vErrors !== null){ -if(_errs167){ -vErrors.length = _errs167; -} -else { -vErrors = null; -} -} -} -} -if(data34.tool_calls !== undefined){ -let data85 = data34.tool_calls; -if((data85 !== null) && (!(Array.isArray(data85)))){ -const err155 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls",schemaPath:"#/properties/messages/items/properties/tool_calls/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -if(Array.isArray(data85)){ -const len7 = data85.length; -for(let i7=0; i7<len7; i7++){ -let data86 = data85[i7]; -if(data86 && typeof data86 == "object" && !Array.isArray(data86)){ -if(data86.id === undefined){ -const err156 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -if(data86.type === undefined){ -const err157 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -if(data86.function === undefined){ -const err158 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -for(const key13 in data86){ -if(!(((((key13 === "id") || (key13 === "type")) || (key13 === "function")) || (key13 === "duration_ms")) || (key13 === "exit_code"))){ -const err159 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key13},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -} -if(data86.id !== undefined){ -if(typeof data86.id !== "string"){ -const err160 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/id",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data86.type !== undefined){ -if(typeof data86.type !== "string"){ -const err161 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/type",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -} -if(data86.function !== undefined){ -let data89 = data86.function; -if(data89 && typeof data89 == "object" && !Array.isArray(data89)){ -if(data89.name === undefined){ -const err162 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -if(data89.arguments === undefined){ -const err163 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -for(const key14 in data89){ -if(!((key14 === "name") || (key14 === "arguments"))){ -const err164 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key14},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data89.name !== undefined){ -if(typeof data89.name !== "string"){ -const err165 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function/name",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -if(data89.arguments !== undefined){ -if(typeof data89.arguments !== "string"){ -const err166 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function/arguments",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -} -else { -const err167 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -if(data86.duration_ms !== undefined){ -let data92 = data86.duration_ms; -if(!((typeof data92 == "number") && (!(data92 % 1) && !isNaN(data92)))){ -const err168 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/duration_ms",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -} -if(data86.exit_code !== undefined){ -let data93 = data86.exit_code; -if(!((typeof data93 == "number") && (!(data93 % 1) && !isNaN(data93)))){ -const err169 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/exit_code",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -} -} -else { -const err170 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -} -} -} -if(data34.tool_call_id !== undefined){ -if(typeof data34.tool_call_id !== "string"){ -const err171 = {instancePath:instancePath+"/messages/" + i2+"/tool_call_id",schemaPath:"#/properties/messages/items/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -} -if(data34.name !== undefined){ -if(typeof data34.name !== "string"){ -const err172 = {instancePath:instancePath+"/messages/" + i2+"/name",schemaPath:"#/properties/messages/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -} -if(data34.authored !== undefined){ -if(typeof data34.authored !== "boolean"){ -const err173 = {instancePath:instancePath+"/messages/" + i2+"/authored",schemaPath:"#/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -if(data34.sent_at !== undefined){ -let data97 = data34.sent_at; -if((data97 !== null) && (typeof data97 !== "string")){ -const err174 = {instancePath:instancePath+"/messages/" + i2+"/sent_at",schemaPath:"#/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -} -if(data34.usage !== undefined){ -let data98 = data34.usage; -if((data98 !== null) && (!(data98 && typeof data98 == "object" && !Array.isArray(data98)))){ -const err175 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -if(data98 && typeof data98 == "object" && !Array.isArray(data98)){ -if(data98.prompt_tokens === undefined){ -const err176 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -if(data98.completion_tokens === undefined){ -const err177 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -for(const key15 in data98){ -if(!((((((key15 === "reported") || (key15 === "cost")) || (key15 === "prompt_tokens")) || (key15 === "completion_tokens")) || (key15 === "prompt_tokens_details")) || (key15 === "completion_tokens_details"))){ -const err178 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key15},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -if(data98.reported !== undefined){ -if(typeof data98.reported !== "boolean"){ -const err179 = {instancePath:instancePath+"/messages/" + i2+"/usage/reported",schemaPath:"#/properties/messages/items/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -if(data98.cost !== undefined){ -let data100 = data98.cost; -if((data100 !== null) && (!(typeof data100 == "number"))){ -const err180 = {instancePath:instancePath+"/messages/" + i2+"/usage/cost",schemaPath:"#/properties/messages/items/properties/usage/properties/cost/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -} -if(data98.prompt_tokens !== undefined){ -let data101 = data98.prompt_tokens; -if(!((typeof data101 == "number") && (!(data101 % 1) && !isNaN(data101)))){ -const err181 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -} -if(data98.completion_tokens !== undefined){ -let data102 = data98.completion_tokens; -if(!((typeof data102 == "number") && (!(data102 % 1) && !isNaN(data102)))){ -const err182 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -} -if(data98.prompt_tokens_details !== undefined){ -let data103 = data98.prompt_tokens_details; -if((data103 !== null) && (!(data103 && typeof data103 == "object" && !Array.isArray(data103)))){ -const err183 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.cached_tokens === undefined){ -const err184 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -for(const key16 in data103){ -if(!(key16 === "cached_tokens")){ -const err185 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key16},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -if(data103.cached_tokens !== undefined){ -let data104 = data103.cached_tokens; -if(!((typeof data104 == "number") && (!(data104 % 1) && !isNaN(data104)))){ -const err186 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -} -} -} -if(data98.completion_tokens_details !== undefined){ -let data105 = data98.completion_tokens_details; -if((data105 !== null) && (!(data105 && typeof data105 == "object" && !Array.isArray(data105)))){ -const err187 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -if(data105 && typeof data105 == "object" && !Array.isArray(data105)){ -if(data105.reasoning_tokens === undefined){ -const err188 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -for(const key17 in data105){ -if(!(key17 === "reasoning_tokens")){ -const err189 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key17},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -} -if(data105.reasoning_tokens !== undefined){ -let data106 = data105.reasoning_tokens; -if(!((typeof data106 == "number") && (!(data106 % 1) && !isNaN(data106)))){ -const err190 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -} -} -} -} -} -if(data34.model !== undefined){ -if(typeof data34.model !== "string"){ -const err191 = {instancePath:instancePath+"/messages/" + i2+"/model",schemaPath:"#/properties/messages/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -} -if(data34.rewound_from !== undefined){ -if(typeof data34.rewound_from !== "string"){ -const err192 = {instancePath:instancePath+"/messages/" + i2+"/rewound_from",schemaPath:"#/properties/messages/items/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -} -if(data34.call_id !== undefined){ -if(typeof data34.call_id !== "string"){ -const err193 = {instancePath:instancePath+"/messages/" + i2+"/call_id",schemaPath:"#/properties/messages/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -} -} -else { -const err194 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -} -} -} -if(data.presentation !== undefined){ -let data110 = data.presentation; -if((data110 !== null) && (!(Array.isArray(data110)))){ -const err195 = {instancePath:instancePath+"/presentation",schemaPath:"#/properties/presentation/type",keyword:"type",params:{type: schema160.properties.presentation.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(Array.isArray(data110)){ -const len8 = data110.length; -for(let i8=0; i8<len8; i8++){ -let data111 = data110[i8]; -if(data111 && typeof data111 == "object" && !Array.isArray(data111)){ -if(data111.seq === undefined){ -const err196 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -if(data111.kind === undefined){ -const err197 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -if(data111.payload === undefined){ -const err198 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -for(const key18 in data111){ -if(!(((key18 === "seq") || (key18 === "kind")) || (key18 === "payload"))){ -const err199 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key18},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -} -if(data111.seq !== undefined){ -let data112 = data111.seq; -if(typeof data112 === "string"){ -if(!pattern0.test(data112)){ -const err200 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -if(!(formats0.validate(data112))){ -const err201 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -} -else { -const err202 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -} -if(data111.kind !== undefined){ -if(typeof data111.kind !== "string"){ -const err203 = {instancePath:instancePath+"/presentation/" + i8+"/kind",schemaPath:"#/properties/presentation/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -} -} -else { -const err204 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -} -} -} -if(data.agent_presentations !== undefined){ -let data114 = data.agent_presentations; -if(data114 && typeof data114 == "object" && !Array.isArray(data114)){ -for(const key19 in data114){ -let data115 = data114[key19]; -if((data115 !== null) && (!(Array.isArray(data115)))){ -const err205 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/agent_presentations/additionalProperties/type",keyword:"type",params:{type: schema160.properties.agent_presentations.additionalProperties.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -if(Array.isArray(data115)){ -const len9 = data115.length; -for(let i9=0; i9<len9; i9++){ -let data116 = data115[i9]; -if(data116 && typeof data116 == "object" && !Array.isArray(data116)){ -if(data116.seq === undefined){ -const err206 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -if(data116.kind === undefined){ -const err207 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -if(data116.payload === undefined){ -const err208 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -for(const key20 in data116){ -if(!(((key20 === "seq") || (key20 === "kind")) || (key20 === "payload"))){ -const err209 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key20},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -} -if(data116.seq !== undefined){ -let data117 = data116.seq; -if(typeof data117 === "string"){ -if(!pattern0.test(data117)){ -const err210 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -if(!(formats0.validate(data117))){ -const err211 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -} -else { -const err212 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -} -if(data116.kind !== undefined){ -if(typeof data116.kind !== "string"){ -const err213 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/kind",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -} -} -else { -const err214 = {instancePath:instancePath+"/agent_presentations/" + key19.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -} -} -} -} -else { -const err215 = {instancePath:instancePath+"/agent_presentations",schemaPath:"#/properties/agent_presentations/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -} -if(data.agents !== undefined){ -let data119 = data.agents; -if((data119 !== null) && (!(Array.isArray(data119)))){ -const err216 = {instancePath:instancePath+"/agents",schemaPath:"#/properties/agents/type",keyword:"type",params:{type: schema160.properties.agents.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -if(Array.isArray(data119)){ -const len10 = data119.length; -for(let i10=0; i10<len10; i10++){ -let data120 = data119[i10]; -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.execution_engine === undefined){ -const err217 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -if(data120.id === undefined){ -const err218 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -if(data120.root_id === undefined){ -const err219 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -if(data120.parent_id === undefined){ -const err220 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -if(data120.name === undefined){ -const err221 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -if(data120.model === undefined){ -const err222 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -if(data120.provider === undefined){ -const err223 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -if(data120.effort === undefined){ -const err224 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -if(data120.cwd === undefined){ -const err225 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -if(data120.report === undefined){ -const err226 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -if(data120.status === undefined){ -const err227 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -if(data120.pending_mail === undefined){ -const err228 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -if(data120.lifecycle_phase === undefined){ -const err229 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -if(data120.blocking_reason === undefined){ -const err230 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -if(data120.terminal_cause === undefined){ -const err231 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -if(data120.allowed_controls === undefined){ -const err232 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -for(const key21 in data120){ -if(!(func2.call(schema160.properties.agents.items.properties, key21))){ -const err233 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key21},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -} -if(data120.execution_engine !== undefined){ -if(typeof data120.execution_engine !== "string"){ -const err234 = {instancePath:instancePath+"/agents/" + i10+"/execution_engine",schemaPath:"#/properties/agents/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -} -if(data120.last_turn !== undefined){ -let data122 = data120.last_turn; -if((data122 !== null) && (!(data122 && typeof data122 == "object" && !Array.isArray(data122)))){ -const err235 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -if(data122 && typeof data122 == "object" && !Array.isArray(data122)){ -if(data122.status === undefined){ -const err236 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -if(data122.event_seq === undefined){ -const err237 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -for(const key22 in data122){ -if(!(func2.call(schema160.properties.agents.items.properties.last_turn.properties, key22))){ -const err238 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key22},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -} -if(data122.turn_id !== undefined){ -if(typeof data122.turn_id !== "string"){ -const err239 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/turn_id",schemaPath:"#/properties/agents/items/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -} -if(data122.status !== undefined){ -if(typeof data122.status !== "string"){ -const err240 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/status",schemaPath:"#/properties/agents/items/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data122.started_at !== undefined){ -if(typeof data122.started_at !== "string"){ -const err241 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/started_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data122.finished_at !== undefined){ -if(typeof data122.finished_at !== "string"){ -const err242 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/finished_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -} -if(data122.event_seq !== undefined){ -let data127 = data122.event_seq; -if(typeof data127 === "string"){ -if(!pattern0.test(data127)){ -const err243 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -if(!(formats0.validate(data127))){ -const err244 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -} -else { -const err245 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -} -if(data122.error !== undefined){ -if(typeof data122.error !== "string"){ -const err246 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -} -if(data122.error_truncated !== undefined){ -if(typeof data122.error_truncated !== "boolean"){ -const err247 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_truncated",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -} -if(data122.error_details !== undefined){ -let data130 = data122.error_details; -if((data130 !== null) && (!(data130 && typeof data130 == "object" && !Array.isArray(data130)))){ -const err248 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -if(data130 && typeof data130 == "object" && !Array.isArray(data130)){ -if(data130.reference_id === undefined){ -const err249 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -if(data130.digest === undefined){ -const err250 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -if(data130.size === undefined){ -const err251 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -if(data130.media_type === undefined){ -const err252 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -if(data130.source === undefined){ -const err253 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -for(const key23 in data130){ -if(!((((((((key23 === "inline") || (key23 === "text")) || (key23 === "binary")) || (key23 === "reference_id")) || (key23 === "digest")) || (key23 === "size")) || (key23 === "media_type")) || (key23 === "source"))){ -const err254 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key23},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -} -if(data130.text !== undefined){ -let data131 = data130.text; -if((data131 !== null) && (typeof data131 !== "string")){ -const err255 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/text",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -} -if(data130.binary !== undefined){ -let data132 = data130.binary; -if((typeof data132 !== "string") && (data132 !== null)){ -const err256 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/binary",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -} -if(data130.reference_id !== undefined){ -if(typeof data130.reference_id !== "string"){ -const err257 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/reference_id",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -} -if(data130.digest !== undefined){ -if(typeof data130.digest !== "string"){ -const err258 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/digest",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -} -if(data130.size !== undefined){ -let data135 = data130.size; -if(typeof data135 === "string"){ -if(!pattern0.test(data135)){ -const err259 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -if(!(formats0.validate(data135))){ -const err260 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -} -else { -const err261 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -} -if(data130.media_type !== undefined){ -if(typeof data130.media_type !== "string"){ -const err262 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/media_type",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -} -if(data130.source !== undefined){ -if(typeof data130.source !== "string"){ -const err263 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/source",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -} -} -} -if(data122.model_calls !== undefined){ -let data138 = data122.model_calls; -if(!((typeof data138 == "number") && (!(data138 % 1) && !isNaN(data138)))){ -const err264 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/model_calls",schemaPath:"#/properties/agents/items/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -} -if(data122.compactions !== undefined){ -let data139 = data122.compactions; -if(!((typeof data139 == "number") && (!(data139 % 1) && !isNaN(data139)))){ -const err265 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/compactions",schemaPath:"#/properties/agents/items/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -} -if(data122.last_activity_at !== undefined){ -if(typeof data122.last_activity_at !== "string"){ -const err266 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/last_activity_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -} -} -} -if(data120.id !== undefined){ -if(typeof data120.id !== "string"){ -const err267 = {instancePath:instancePath+"/agents/" + i10+"/id",schemaPath:"#/properties/agents/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -} -if(data120.root_id !== undefined){ -if(typeof data120.root_id !== "string"){ -const err268 = {instancePath:instancePath+"/agents/" + i10+"/root_id",schemaPath:"#/properties/agents/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -} -if(data120.parent_id !== undefined){ -if(typeof data120.parent_id !== "string"){ -const err269 = {instancePath:instancePath+"/agents/" + i10+"/parent_id",schemaPath:"#/properties/agents/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -} -if(data120.name !== undefined){ -if(typeof data120.name !== "string"){ -const err270 = {instancePath:instancePath+"/agents/" + i10+"/name",schemaPath:"#/properties/agents/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -} -if(data120.model !== undefined){ -if(typeof data120.model !== "string"){ -const err271 = {instancePath:instancePath+"/agents/" + i10+"/model",schemaPath:"#/properties/agents/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -} -if(data120.provider !== undefined){ -if(typeof data120.provider !== "string"){ -const err272 = {instancePath:instancePath+"/agents/" + i10+"/provider",schemaPath:"#/properties/agents/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -} -if(data120.effort !== undefined){ -if(typeof data120.effort !== "string"){ -const err273 = {instancePath:instancePath+"/agents/" + i10+"/effort",schemaPath:"#/properties/agents/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -} -if(data120.cwd !== undefined){ -if(typeof data120.cwd !== "string"){ -const err274 = {instancePath:instancePath+"/agents/" + i10+"/cwd",schemaPath:"#/properties/agents/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -} -if(data120.report !== undefined){ -if(typeof data120.report !== "string"){ -const err275 = {instancePath:instancePath+"/agents/" + i10+"/report",schemaPath:"#/properties/agents/items/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -} -if(data120.status !== undefined){ -if(typeof data120.status !== "string"){ -const err276 = {instancePath:instancePath+"/agents/" + i10+"/status",schemaPath:"#/properties/agents/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -} -if(data120.pending_mail !== undefined){ -let data151 = data120.pending_mail; -if(!((typeof data151 == "number") && (!(data151 % 1) && !isNaN(data151)))){ -const err277 = {instancePath:instancePath+"/agents/" + i10+"/pending_mail",schemaPath:"#/properties/agents/items/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -} -if(data120.lifecycle_phase !== undefined){ -if(typeof data120.lifecycle_phase !== "string"){ -const err278 = {instancePath:instancePath+"/agents/" + i10+"/lifecycle_phase",schemaPath:"#/properties/agents/items/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -} -if(data120.blocking_reason !== undefined){ -if(typeof data120.blocking_reason !== "string"){ -const err279 = {instancePath:instancePath+"/agents/" + i10+"/blocking_reason",schemaPath:"#/properties/agents/items/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -} -if(data120.terminal_cause !== undefined){ -if(typeof data120.terminal_cause !== "string"){ -const err280 = {instancePath:instancePath+"/agents/" + i10+"/terminal_cause",schemaPath:"#/properties/agents/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -} -if(data120.allowed_controls !== undefined){ -let data155 = data120.allowed_controls; -if((data155 !== null) && (!(Array.isArray(data155)))){ -const err281 = {instancePath:instancePath+"/agents/" + i10+"/allowed_controls",schemaPath:"#/properties/agents/items/properties/allowed_controls/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -if(Array.isArray(data155)){ -const len11 = data155.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data155[i11] !== "string"){ -const err282 = {instancePath:instancePath+"/agents/" + i10+"/allowed_controls/" + i11,schemaPath:"#/properties/agents/items/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -} -} -} -} -else { -const err283 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -} -} -} -if(data.inbox !== undefined){ -let data157 = data.inbox; -if((data157 !== null) && (!(Array.isArray(data157)))){ -const err284 = {instancePath:instancePath+"/inbox",schemaPath:"#/properties/inbox/type",keyword:"type",params:{type: schema160.properties.inbox.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -if(Array.isArray(data157)){ -const len12 = data157.length; -for(let i12=0; i12<len12; i12++){ -let data158 = data157[i12]; -if(data158 && typeof data158 == "object" && !Array.isArray(data158)){ -if(data158.root_id === undefined){ -const err285 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -if(data158.agent_id === undefined){ -const err286 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -if(data158.seq === undefined){ -const err287 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -if(data158.kind === undefined){ -const err288 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -if(data158.status === undefined){ -const err289 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -if(data158.payload === undefined){ -const err290 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -for(const key24 in data158){ -if(!(func2.call(schema160.properties.inbox.items.properties, key24))){ -const err291 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key24},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data158.delivery_seq !== undefined){ -let data159 = data158.delivery_seq; -if(typeof data159 === "string"){ -if(!pattern0.test(data159)){ -const err292 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -if(!(formats0.validate(data159))){ -const err293 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -} -else { -const err294 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -} -if(data158.origin !== undefined){ -if(typeof data158.origin !== "string"){ -const err295 = {instancePath:instancePath+"/inbox/" + i12+"/origin",schemaPath:"#/properties/inbox/items/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -} -if(data158.command_client_id !== undefined){ -if(typeof data158.command_client_id !== "string"){ -const err296 = {instancePath:instancePath+"/inbox/" + i12+"/command_client_id",schemaPath:"#/properties/inbox/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -} -if(data158.command_id !== undefined){ -if(typeof data158.command_id !== "string"){ -const err297 = {instancePath:instancePath+"/inbox/" + i12+"/command_id",schemaPath:"#/properties/inbox/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -} -if(data158.steer_turn_id !== undefined){ -if(typeof data158.steer_turn_id !== "string"){ -const err298 = {instancePath:instancePath+"/inbox/" + i12+"/steer_turn_id",schemaPath:"#/properties/inbox/items/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -} -if(data158.preview !== undefined){ -let data164 = data158.preview; -if((data164 !== null) && (!(data164 && typeof data164 == "object" && !Array.isArray(data164)))){ -const err299 = {instancePath:instancePath+"/inbox/" + i12+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -if(data164 && typeof data164 == "object" && !Array.isArray(data164)){ -if(data164.text === undefined){ -const err300 = {instancePath:instancePath+"/inbox/" + i12+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -for(const key25 in data164){ -if(!(((((key25 === "design_context") || (key25 === "text")) || (key25 === "truncated")) || (key25 === "attachments")) || (key25 === "attachment_count"))){ -const err301 = {instancePath:instancePath+"/inbox/" + i12+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key25},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -} -if(data164.design_context !== undefined){ -let data165 = data164.design_context; -if((data165 !== null) && (!(data165 && typeof data165 == "object" && !Array.isArray(data165)))){ -const err302 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -if(data165 && typeof data165 == "object" && !Array.isArray(data165)){ -if(data165.context_attachment_id === undefined){ -const err303 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -if(data165.elements === undefined){ -const err304 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -if(data165.element_count === undefined){ -const err305 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -for(const key26 in data165){ -if(!((((((key26 === "context_attachment_id") || (key26 === "screenshot_attachment_id")) || (key26 === "elements")) || (key26 === "element_count")) || (key26 === "page_url")) || (key26 === "page_title"))){ -const err306 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key26},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -} -if(data165.context_attachment_id !== undefined){ -if(typeof data165.context_attachment_id !== "string"){ -const err307 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/context_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -} -if(data165.screenshot_attachment_id !== undefined){ -if(typeof data165.screenshot_attachment_id !== "string"){ -const err308 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -} -if(data165.elements !== undefined){ -let data168 = data165.elements; -if((data168 !== null) && (!(Array.isArray(data168)))){ -const err309 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -if(Array.isArray(data168)){ -const len13 = data168.length; -for(let i13=0; i13<len13; i13++){ -let data169 = data168[i13]; -if(data169 && typeof data169 == "object" && !Array.isArray(data169)){ -if(data169.label === undefined){ -const err310 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -for(const key27 in data169){ -if(!((key27 === "label") || (key27 === "selector"))){ -const err311 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key27},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -} -if(data169.label !== undefined){ -if(typeof data169.label !== "string"){ -const err312 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13+"/label",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -} -if(data169.selector !== undefined){ -if(typeof data169.selector !== "string"){ -const err313 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13+"/selector",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -} -} -else { -const err314 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -} -} -} -if(data165.element_count !== undefined){ -let data172 = data165.element_count; -if(!((typeof data172 == "number") && (!(data172 % 1) && !isNaN(data172)))){ -const err315 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/element_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -} -if(data165.page_url !== undefined){ -if(typeof data165.page_url !== "string"){ -const err316 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/page_url",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -} -if(data165.page_title !== undefined){ -if(typeof data165.page_title !== "string"){ -const err317 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/page_title",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -} -} -} -if(data164.text !== undefined){ -if(typeof data164.text !== "string"){ -const err318 = {instancePath:instancePath+"/inbox/" + i12+"/preview/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -} -if(data164.truncated !== undefined){ -if(typeof data164.truncated !== "boolean"){ -const err319 = {instancePath:instancePath+"/inbox/" + i12+"/preview/truncated",schemaPath:"#/properties/inbox/items/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -} -if(data164.attachments !== undefined){ -let data177 = data164.attachments; -if((data177 !== null) && (!(Array.isArray(data177)))){ -const err320 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -if(Array.isArray(data177)){ -const len14 = data177.length; -for(let i14=0; i14<len14; i14++){ -let data178 = data177[i14]; -if(data178 && typeof data178 == "object" && !Array.isArray(data178)){ -if(data178.kind === undefined){ -const err321 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -if(data178.content === undefined){ -const err322 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -for(const key28 in data178){ -if(!(((key28 === "kind") || (key28 === "name")) || (key28 === "content"))){ -const err323 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key28},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -} -if(data178.kind !== undefined){ -if(typeof data178.kind !== "string"){ -const err324 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/kind",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -} -if(data178.name !== undefined){ -if(typeof data178.name !== "string"){ -const err325 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/name",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -} -if(data178.content !== undefined){ -let data181 = data178.content; -if(data181 && typeof data181 == "object" && !Array.isArray(data181)){ -if(data181.reference_id === undefined){ -const err326 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -if(data181.digest === undefined){ -const err327 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -if(data181.size === undefined){ -const err328 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -if(data181.media_type === undefined){ -const err329 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -if(data181.source === undefined){ -const err330 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -for(const key29 in data181){ -if(!((((((((key29 === "inline") || (key29 === "text")) || (key29 === "binary")) || (key29 === "reference_id")) || (key29 === "digest")) || (key29 === "size")) || (key29 === "media_type")) || (key29 === "source"))){ -const err331 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key29},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -} -if(data181.text !== undefined){ -let data182 = data181.text; -if((data182 !== null) && (typeof data182 !== "string")){ -const err332 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -} -if(data181.binary !== undefined){ -let data183 = data181.binary; -if((typeof data183 !== "string") && (data183 !== null)){ -const err333 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/binary",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -} -if(data181.reference_id !== undefined){ -if(typeof data181.reference_id !== "string"){ -const err334 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/reference_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -} -if(data181.digest !== undefined){ -if(typeof data181.digest !== "string"){ -const err335 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/digest",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -if(data181.size !== undefined){ -let data186 = data181.size; -if(typeof data186 === "string"){ -if(!pattern0.test(data186)){ -const err336 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -if(!(formats0.validate(data186))){ -const err337 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -} -else { -const err338 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -} -if(data181.media_type !== undefined){ -if(typeof data181.media_type !== "string"){ -const err339 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/media_type",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -} -if(data181.source !== undefined){ -if(typeof data181.source !== "string"){ -const err340 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/source",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -} -} -else { -const err341 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -} -} -else { -const err342 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -} -} -} -if(data164.attachment_count !== undefined){ -let data189 = data164.attachment_count; -if(!((typeof data189 == "number") && (!(data189 % 1) && !isNaN(data189)))){ -const err343 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachment_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -} -} -} -if(data158.root_id !== undefined){ -if(typeof data158.root_id !== "string"){ -const err344 = {instancePath:instancePath+"/inbox/" + i12+"/root_id",schemaPath:"#/properties/inbox/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -} -if(data158.agent_id !== undefined){ -if(typeof data158.agent_id !== "string"){ -const err345 = {instancePath:instancePath+"/inbox/" + i12+"/agent_id",schemaPath:"#/properties/inbox/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -} -if(data158.seq !== undefined){ -let data192 = data158.seq; -if(typeof data192 === "string"){ -if(!pattern0.test(data192)){ -const err346 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -if(!(formats0.validate(data192))){ -const err347 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -} -else { -const err348 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -} -if(data158.kind !== undefined){ -if(typeof data158.kind !== "string"){ -const err349 = {instancePath:instancePath+"/inbox/" + i12+"/kind",schemaPath:"#/properties/inbox/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -} -if(data158.status !== undefined){ -if(typeof data158.status !== "string"){ -const err350 = {instancePath:instancePath+"/inbox/" + i12+"/status",schemaPath:"#/properties/inbox/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -} -if(data158.payload !== undefined){ -let data195 = data158.payload; -if(data195 && typeof data195 == "object" && !Array.isArray(data195)){ -if(data195.reference_id === undefined){ -const err351 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -if(data195.digest === undefined){ -const err352 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -if(data195.size === undefined){ -const err353 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -if(data195.media_type === undefined){ -const err354 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -if(data195.source === undefined){ -const err355 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -for(const key30 in data195){ -if(!((((((((key30 === "inline") || (key30 === "text")) || (key30 === "binary")) || (key30 === "reference_id")) || (key30 === "digest")) || (key30 === "size")) || (key30 === "media_type")) || (key30 === "source"))){ -const err356 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key30},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -} -if(data195.text !== undefined){ -let data196 = data195.text; -if((data196 !== null) && (typeof data196 !== "string")){ -const err357 = {instancePath:instancePath+"/inbox/" + i12+"/payload/text",schemaPath:"#/properties/inbox/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -} -if(data195.binary !== undefined){ -let data197 = data195.binary; -if((typeof data197 !== "string") && (data197 !== null)){ -const err358 = {instancePath:instancePath+"/inbox/" + i12+"/payload/binary",schemaPath:"#/properties/inbox/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -} -if(data195.reference_id !== undefined){ -if(typeof data195.reference_id !== "string"){ -const err359 = {instancePath:instancePath+"/inbox/" + i12+"/payload/reference_id",schemaPath:"#/properties/inbox/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -} -if(data195.digest !== undefined){ -if(typeof data195.digest !== "string"){ -const err360 = {instancePath:instancePath+"/inbox/" + i12+"/payload/digest",schemaPath:"#/properties/inbox/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -} -if(data195.size !== undefined){ -let data200 = data195.size; -if(typeof data200 === "string"){ -if(!pattern0.test(data200)){ -const err361 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -if(!(formats0.validate(data200))){ -const err362 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -} -else { -const err363 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -} -if(data195.media_type !== undefined){ -if(typeof data195.media_type !== "string"){ -const err364 = {instancePath:instancePath+"/inbox/" + i12+"/payload/media_type",schemaPath:"#/properties/inbox/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -} -if(data195.source !== undefined){ -if(typeof data195.source !== "string"){ -const err365 = {instancePath:instancePath+"/inbox/" + i12+"/payload/source",schemaPath:"#/properties/inbox/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -} -} -else { -const err366 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -} -} -else { -const err367 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -} -} -} -if(data.blackboard !== undefined){ -let data203 = data.blackboard; -if((data203 !== null) && (!(Array.isArray(data203)))){ -const err368 = {instancePath:instancePath+"/blackboard",schemaPath:"#/properties/blackboard/type",keyword:"type",params:{type: schema160.properties.blackboard.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -if(Array.isArray(data203)){ -const len15 = data203.length; -for(let i15=0; i15<len15; i15++){ -let data204 = data203[i15]; -if(data204 && typeof data204 == "object" && !Array.isArray(data204)){ -if(data204.key === undefined){ -const err369 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -if(data204.version === undefined){ -const err370 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -if(data204.author_agent_id === undefined){ -const err371 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -if(data204.payload === undefined){ -const err372 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -for(const key31 in data204){ -if(!((((key31 === "key") || (key31 === "version")) || (key31 === "author_agent_id")) || (key31 === "payload"))){ -const err373 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key31},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -} -if(data204.key !== undefined){ -if(typeof data204.key !== "string"){ -const err374 = {instancePath:instancePath+"/blackboard/" + i15+"/key",schemaPath:"#/properties/blackboard/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -} -if(data204.version !== undefined){ -let data206 = data204.version; -if(typeof data206 === "string"){ -if(!pattern0.test(data206)){ -const err375 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -if(!(formats0.validate(data206))){ -const err376 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -} -else { -const err377 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -} -if(data204.author_agent_id !== undefined){ -if(typeof data204.author_agent_id !== "string"){ -const err378 = {instancePath:instancePath+"/blackboard/" + i15+"/author_agent_id",schemaPath:"#/properties/blackboard/items/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -} -if(data204.payload !== undefined){ -let data208 = data204.payload; -if(data208 && typeof data208 == "object" && !Array.isArray(data208)){ -if(data208.reference_id === undefined){ -const err379 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -if(data208.digest === undefined){ -const err380 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -if(data208.size === undefined){ -const err381 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -if(data208.media_type === undefined){ -const err382 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -if(data208.source === undefined){ -const err383 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -for(const key32 in data208){ -if(!((((((((key32 === "inline") || (key32 === "text")) || (key32 === "binary")) || (key32 === "reference_id")) || (key32 === "digest")) || (key32 === "size")) || (key32 === "media_type")) || (key32 === "source"))){ -const err384 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key32},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -} -if(data208.text !== undefined){ -let data209 = data208.text; -if((data209 !== null) && (typeof data209 !== "string")){ -const err385 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/text",schemaPath:"#/properties/blackboard/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema160.properties.blackboard.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -} -if(data208.binary !== undefined){ -let data210 = data208.binary; -if((typeof data210 !== "string") && (data210 !== null)){ -const err386 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/binary",schemaPath:"#/properties/blackboard/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema160.properties.blackboard.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -if(data208.reference_id !== undefined){ -if(typeof data208.reference_id !== "string"){ -const err387 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/reference_id",schemaPath:"#/properties/blackboard/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -} -if(data208.digest !== undefined){ -if(typeof data208.digest !== "string"){ -const err388 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/digest",schemaPath:"#/properties/blackboard/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err388]; -} -else { -vErrors.push(err388); -} -errors++; -} -} -if(data208.size !== undefined){ -let data213 = data208.size; -if(typeof data213 === "string"){ -if(!pattern0.test(data213)){ -const err389 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err389]; -} -else { -vErrors.push(err389); -} -errors++; -} -if(!(formats0.validate(data213))){ -const err390 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err390]; -} -else { -vErrors.push(err390); -} -errors++; -} -} -else { -const err391 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err391]; -} -else { -vErrors.push(err391); -} -errors++; -} -} -if(data208.media_type !== undefined){ -if(typeof data208.media_type !== "string"){ -const err392 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/media_type",schemaPath:"#/properties/blackboard/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err392]; -} -else { -vErrors.push(err392); -} -errors++; -} -} -if(data208.source !== undefined){ -if(typeof data208.source !== "string"){ -const err393 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/source",schemaPath:"#/properties/blackboard/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err393]; -} -else { -vErrors.push(err393); -} -errors++; -} -} -} -else { -const err394 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err394]; -} -else { -vErrors.push(err394); -} -errors++; -} -} -} -else { -const err395 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err395]; -} -else { -vErrors.push(err395); -} -errors++; -} -} -} -} -if(data.budgets !== undefined){ -let data216 = data.budgets; -if((data216 !== null) && (!(Array.isArray(data216)))){ -const err396 = {instancePath:instancePath+"/budgets",schemaPath:"#/properties/budgets/type",keyword:"type",params:{type: schema160.properties.budgets.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err396]; -} -else { -vErrors.push(err396); -} -errors++; -} -if(Array.isArray(data216)){ -const len16 = data216.length; -for(let i16=0; i16<len16; i16++){ -let data217 = data216[i16]; -if(data217 && typeof data217 == "object" && !Array.isArray(data217)){ -if(data217.agent_id === undefined){ -const err397 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err397]; -} -else { -vErrors.push(err397); -} -errors++; -} -if(data217.state === undefined){ -const err398 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err398]; -} -else { -vErrors.push(err398); -} -errors++; -} -for(const key33 in data217){ -if(!((key33 === "agent_id") || (key33 === "state"))){ -const err399 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key33},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err399]; -} -else { -vErrors.push(err399); -} -errors++; -} -} -if(data217.agent_id !== undefined){ -if(typeof data217.agent_id !== "string"){ -const err400 = {instancePath:instancePath+"/budgets/" + i16+"/agent_id",schemaPath:"#/properties/budgets/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err400]; -} -else { -vErrors.push(err400); -} -errors++; -} -} -if(data217.state !== undefined){ -let data219 = data217.state; -if(data219 && typeof data219 == "object" && !Array.isArray(data219)){ -if(data219.kind === undefined){ -const err401 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err401]; -} -else { -vErrors.push(err401); -} -errors++; -} -if(data219.limit === undefined){ -const err402 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err402]; -} -else { -vErrors.push(err402); -} -errors++; -} -if(data219.used === undefined){ -const err403 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err403]; -} -else { -vErrors.push(err403); -} -errors++; -} -if(data219.reserved === undefined){ -const err404 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err404]; -} -else { -vErrors.push(err404); -} -errors++; -} -if(data219.remaining === undefined){ -const err405 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err405]; -} -else { -vErrors.push(err405); -} -errors++; -} -if(data219.uncertain === undefined){ -const err406 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err406]; -} -else { -vErrors.push(err406); -} -errors++; -} -if(data219.incomplete === undefined){ -const err407 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err407]; -} -else { -vErrors.push(err407); -} -errors++; -} -for(const key34 in data219){ -if(!(((((((key34 === "kind") || (key34 === "limit")) || (key34 === "used")) || (key34 === "reserved")) || (key34 === "remaining")) || (key34 === "uncertain")) || (key34 === "incomplete"))){ -const err408 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key34},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err408]; -} -else { -vErrors.push(err408); -} -errors++; -} -} -if(data219.kind !== undefined){ -if(typeof data219.kind !== "string"){ -const err409 = {instancePath:instancePath+"/budgets/" + i16+"/state/kind",schemaPath:"#/properties/budgets/items/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err409]; -} -else { -vErrors.push(err409); -} -errors++; -} -} -if(data219.limit !== undefined){ -let data221 = data219.limit; -if((typeof data221 !== "string") && (data221 !== null)){ -const err410 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/type",keyword:"type",params:{type: schema160.properties.budgets.items.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err410]; -} -else { -vErrors.push(err410); -} -errors++; -} -if(typeof data221 === "string"){ -if(!pattern0.test(data221)){ -const err411 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err411]; -} -else { -vErrors.push(err411); -} -errors++; -} -if(!(formats0.validate(data221))){ -const err412 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err412]; -} -else { -vErrors.push(err412); -} -errors++; -} -} -} -if(data219.used !== undefined){ -let data222 = data219.used; -if(typeof data222 === "string"){ -if(!pattern0.test(data222)){ -const err413 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err413]; -} -else { -vErrors.push(err413); -} -errors++; -} -if(!(formats0.validate(data222))){ -const err414 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err414]; -} -else { -vErrors.push(err414); -} -errors++; -} -} -else { -const err415 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err415]; -} -else { -vErrors.push(err415); -} -errors++; -} -} -if(data219.reserved !== undefined){ -let data223 = data219.reserved; -if(typeof data223 === "string"){ -if(!pattern0.test(data223)){ -const err416 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err416]; -} -else { -vErrors.push(err416); -} -errors++; -} -if(!(formats0.validate(data223))){ -const err417 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err417]; -} -else { -vErrors.push(err417); -} -errors++; -} -} -else { -const err418 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err418]; -} -else { -vErrors.push(err418); -} -errors++; -} -} -if(data219.remaining !== undefined){ -let data224 = data219.remaining; -if((typeof data224 !== "string") && (data224 !== null)){ -const err419 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/type",keyword:"type",params:{type: schema160.properties.budgets.items.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err419]; -} -else { -vErrors.push(err419); -} -errors++; -} -if(typeof data224 === "string"){ -if(!pattern0.test(data224)){ -const err420 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err420]; -} -else { -vErrors.push(err420); -} -errors++; -} -if(!(formats0.validate(data224))){ -const err421 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err421]; -} -else { -vErrors.push(err421); -} -errors++; -} -} -} -if(data219.uncertain !== undefined){ -let data225 = data219.uncertain; -if(typeof data225 === "string"){ -if(!pattern0.test(data225)){ -const err422 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err422]; -} -else { -vErrors.push(err422); -} -errors++; -} -if(!(formats0.validate(data225))){ -const err423 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err423]; -} -else { -vErrors.push(err423); -} -errors++; -} -} -else { -const err424 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err424]; -} -else { -vErrors.push(err424); -} -errors++; -} -} -if(data219.incomplete !== undefined){ -if(typeof data219.incomplete !== "boolean"){ -const err425 = {instancePath:instancePath+"/budgets/" + i16+"/state/incomplete",schemaPath:"#/properties/budgets/items/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err425]; -} -else { -vErrors.push(err425); -} -errors++; -} -} -} -else { -const err426 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err426]; -} -else { -vErrors.push(err426); -} -errors++; -} -} -} -else { -const err427 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err427]; -} -else { -vErrors.push(err427); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data227 = data.accounting; -if(data227 && typeof data227 == "object" && !Array.isArray(data227)){ -if(data227.root_id === undefined){ -const err428 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err428]; -} -else { -vErrors.push(err428); -} -errors++; -} -if(data227.agent_id === undefined){ -const err429 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err429]; -} -else { -vErrors.push(err429); -} -errors++; -} -if(data227.scope === undefined){ -const err430 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err430]; -} -else { -vErrors.push(err430); -} -errors++; -} -if(data227.revision === undefined){ -const err431 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err431]; -} -else { -vErrors.push(err431); -} -errors++; -} -if(data227.reported_cost_micros === undefined){ -const err432 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err432]; -} -else { -vErrors.push(err432); -} -errors++; -} -if(data227.estimated_cost_micros === undefined){ -const err433 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err433]; -} -else { -vErrors.push(err433); -} -errors++; -} -if(data227.reported_cost_calls === undefined){ -const err434 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err434]; -} -else { -vErrors.push(err434); -} -errors++; -} -if(data227.estimated_cost_calls === undefined){ -const err435 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err435]; -} -else { -vErrors.push(err435); -} -errors++; -} -if(data227.unknown_cost_calls === undefined){ -const err436 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err436]; -} -else { -vErrors.push(err436); -} -errors++; -} -if(data227.reported_calls === undefined){ -const err437 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err437]; -} -else { -vErrors.push(err437); -} -errors++; -} -if(data227.estimated_calls === undefined){ -const err438 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err438]; -} -else { -vErrors.push(err438); -} -errors++; -} -if(data227.pending_calls === undefined){ -const err439 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err439]; -} -else { -vErrors.push(err439); -} -errors++; -} -for(const key35 in data227){ -if(!(func2.call(schema160.properties.accounting.properties, key35))){ -const err440 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key35},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err440]; -} -else { -vErrors.push(err440); -} -errors++; -} -} -if(data227.root_id !== undefined){ -if(typeof data227.root_id !== "string"){ -const err441 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err441]; -} -else { -vErrors.push(err441); -} -errors++; -} -} -if(data227.agent_id !== undefined){ -if(typeof data227.agent_id !== "string"){ -const err442 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err442]; -} -else { -vErrors.push(err442); -} -errors++; -} -} -if(data227.scope !== undefined){ -if(typeof data227.scope !== "string"){ -const err443 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err443]; -} -else { -vErrors.push(err443); -} -errors++; -} -} -if(data227.revision !== undefined){ -let data231 = data227.revision; -if(typeof data231 === "string"){ -if(!pattern0.test(data231)){ -const err444 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err444]; -} -else { -vErrors.push(err444); -} -errors++; -} -if(!(formats0.validate(data231))){ -const err445 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err445]; -} -else { -vErrors.push(err445); -} -errors++; -} -} -else { -const err446 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err446]; -} -else { -vErrors.push(err446); -} -errors++; -} -} -if(data227.reported_cost_micros !== undefined){ -let data232 = data227.reported_cost_micros; -if(typeof data232 === "string"){ -if(!pattern0.test(data232)){ -const err447 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err447]; -} -else { -vErrors.push(err447); -} -errors++; -} -if(!(formats0.validate(data232))){ -const err448 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err448]; -} -else { -vErrors.push(err448); -} -errors++; -} -} -else { -const err449 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err449]; -} -else { -vErrors.push(err449); -} -errors++; -} -} -if(data227.estimated_cost_micros !== undefined){ -let data233 = data227.estimated_cost_micros; -if(typeof data233 === "string"){ -if(!pattern0.test(data233)){ -const err450 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err450]; -} -else { -vErrors.push(err450); -} -errors++; -} -if(!(formats0.validate(data233))){ -const err451 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err451]; -} -else { -vErrors.push(err451); -} -errors++; -} -} -else { -const err452 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err452]; -} -else { -vErrors.push(err452); -} -errors++; -} -} -if(data227.reported_cost_calls !== undefined){ -let data234 = data227.reported_cost_calls; -if(typeof data234 === "string"){ -if(!pattern0.test(data234)){ -const err453 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err453]; -} -else { -vErrors.push(err453); -} -errors++; -} -if(!(formats0.validate(data234))){ -const err454 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err454]; -} -else { -vErrors.push(err454); -} -errors++; -} -} -else { -const err455 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err455]; -} -else { -vErrors.push(err455); -} -errors++; -} -} -if(data227.estimated_cost_calls !== undefined){ -let data235 = data227.estimated_cost_calls; -if(typeof data235 === "string"){ -if(!pattern0.test(data235)){ -const err456 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err456]; -} -else { -vErrors.push(err456); -} -errors++; -} -if(!(formats0.validate(data235))){ -const err457 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err457]; -} -else { -vErrors.push(err457); -} -errors++; -} -} -else { -const err458 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err458]; -} -else { -vErrors.push(err458); -} -errors++; -} -} -if(data227.unknown_cost_calls !== undefined){ -let data236 = data227.unknown_cost_calls; -if(typeof data236 === "string"){ -if(!pattern0.test(data236)){ -const err459 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err459]; -} -else { -vErrors.push(err459); -} -errors++; -} -if(!(formats0.validate(data236))){ -const err460 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err460]; -} -else { -vErrors.push(err460); -} -errors++; -} -} -else { -const err461 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err461]; -} -else { -vErrors.push(err461); -} -errors++; -} -} -if(data227.reported_calls !== undefined){ -let data237 = data227.reported_calls; -if(typeof data237 === "string"){ -if(!pattern0.test(data237)){ -const err462 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err462]; -} -else { -vErrors.push(err462); -} -errors++; -} -if(!(formats0.validate(data237))){ -const err463 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err463]; -} -else { -vErrors.push(err463); -} -errors++; -} -} -else { -const err464 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err464]; -} -else { -vErrors.push(err464); -} -errors++; -} -} -if(data227.estimated_calls !== undefined){ -let data238 = data227.estimated_calls; -if(typeof data238 === "string"){ -if(!pattern0.test(data238)){ -const err465 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err465]; -} -else { -vErrors.push(err465); -} -errors++; -} -if(!(formats0.validate(data238))){ -const err466 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err466]; -} -else { -vErrors.push(err466); -} -errors++; -} -} -else { -const err467 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err467]; -} -else { -vErrors.push(err467); -} -errors++; -} -} -if(data227.pending_calls !== undefined){ -let data239 = data227.pending_calls; -if(typeof data239 === "string"){ -if(!pattern0.test(data239)){ -const err468 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err468]; -} -else { -vErrors.push(err468); -} -errors++; -} -if(!(formats0.validate(data239))){ -const err469 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err469]; -} -else { -vErrors.push(err469); -} -errors++; -} -} -else { -const err470 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err470]; -} -else { -vErrors.push(err470); -} -errors++; -} -} -} -else { -const err471 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err471]; -} -else { -vErrors.push(err471); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data240 = data.capabilities; -if((data240 !== null) && (!(Array.isArray(data240)))){ -const err472 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema160.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err472]; -} -else { -vErrors.push(err472); -} -errors++; -} -if(Array.isArray(data240)){ -const len17 = data240.length; -for(let i17=0; i17<len17; i17++){ -let data241 = data240[i17]; -if(data241 && typeof data241 == "object" && !Array.isArray(data241)){ -if(data241.id === undefined){ -const err473 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err473]; -} -else { -vErrors.push(err473); -} -errors++; -} -if(data241.root_id === undefined){ -const err474 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err474]; -} -else { -vErrors.push(err474); -} -errors++; -} -if(data241.agent_id === undefined){ -const err475 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err475]; -} -else { -vErrors.push(err475); -} -errors++; -} -if(data241.issuer_agent_id === undefined){ -const err476 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err476]; -} -else { -vErrors.push(err476); -} -errors++; -} -if(data241.operations === undefined){ -const err477 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err477]; -} -else { -vErrors.push(err477); -} -errors++; -} -if(data241.scopes === undefined){ -const err478 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err478]; -} -else { -vErrors.push(err478); -} -errors++; -} -if(data241.mcp === undefined){ -const err479 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err479]; -} -else { -vErrors.push(err479); -} -errors++; -} -if(data241.mcp_all === undefined){ -const err480 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err480]; -} -else { -vErrors.push(err480); -} -errors++; -} -if(data241.generation === undefined){ -const err481 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err481]; -} -else { -vErrors.push(err481); -} -errors++; -} -if(data241.status === undefined){ -const err482 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err482]; -} -else { -vErrors.push(err482); -} -errors++; -} -if(data241.expires_at === undefined){ -const err483 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err483]; -} -else { -vErrors.push(err483); -} -errors++; -} -if(data241.created_at === undefined){ -const err484 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err484]; -} -else { -vErrors.push(err484); -} -errors++; -} -if(data241.updated_at === undefined){ -const err485 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err485]; -} -else { -vErrors.push(err485); -} -errors++; -} -for(const key36 in data241){ -if(!(func2.call(schema160.properties.capabilities.items.properties, key36))){ -const err486 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key36},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err486]; -} -else { -vErrors.push(err486); -} -errors++; -} -} -if(data241.id !== undefined){ -if(typeof data241.id !== "string"){ -const err487 = {instancePath:instancePath+"/capabilities/" + i17+"/id",schemaPath:"#/properties/capabilities/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err487]; -} -else { -vErrors.push(err487); -} -errors++; -} -} -if(data241.root_id !== undefined){ -if(typeof data241.root_id !== "string"){ -const err488 = {instancePath:instancePath+"/capabilities/" + i17+"/root_id",schemaPath:"#/properties/capabilities/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err488]; -} -else { -vErrors.push(err488); -} -errors++; -} -} -if(data241.agent_id !== undefined){ -if(typeof data241.agent_id !== "string"){ -const err489 = {instancePath:instancePath+"/capabilities/" + i17+"/agent_id",schemaPath:"#/properties/capabilities/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err489]; -} -else { -vErrors.push(err489); -} -errors++; -} -} -if(data241.issuer_agent_id !== undefined){ -if(typeof data241.issuer_agent_id !== "string"){ -const err490 = {instancePath:instancePath+"/capabilities/" + i17+"/issuer_agent_id",schemaPath:"#/properties/capabilities/items/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err490]; -} -else { -vErrors.push(err490); -} -errors++; -} -} -if(data241.operations !== undefined){ -let data246 = data241.operations; -if((data246 !== null) && (!(Array.isArray(data246)))){ -const err491 = {instancePath:instancePath+"/capabilities/" + i17+"/operations",schemaPath:"#/properties/capabilities/items/properties/operations/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err491]; -} -else { -vErrors.push(err491); -} -errors++; -} -if(Array.isArray(data246)){ -const len18 = data246.length; -for(let i18=0; i18<len18; i18++){ -if(typeof data246[i18] !== "string"){ -const err492 = {instancePath:instancePath+"/capabilities/" + i17+"/operations/" + i18,schemaPath:"#/properties/capabilities/items/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err492]; -} -else { -vErrors.push(err492); -} -errors++; -} -} -} -} -if(data241.scopes !== undefined){ -let data248 = data241.scopes; -if((data248 !== null) && (!(Array.isArray(data248)))){ -const err493 = {instancePath:instancePath+"/capabilities/" + i17+"/scopes",schemaPath:"#/properties/capabilities/items/properties/scopes/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err493]; -} -else { -vErrors.push(err493); -} -errors++; -} -if(Array.isArray(data248)){ -const len19 = data248.length; -for(let i19=0; i19<len19; i19++){ -if(typeof data248[i19] !== "string"){ -const err494 = {instancePath:instancePath+"/capabilities/" + i17+"/scopes/" + i19,schemaPath:"#/properties/capabilities/items/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err494]; -} -else { -vErrors.push(err494); -} -errors++; -} -} -} -} -if(data241.file_scope !== undefined){ -if(typeof data241.file_scope !== "string"){ -const err495 = {instancePath:instancePath+"/capabilities/" + i17+"/file_scope",schemaPath:"#/properties/capabilities/items/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err495]; -} -else { -vErrors.push(err495); -} -errors++; -} -} -if(data241.file_issuer_id !== undefined){ -if(typeof data241.file_issuer_id !== "string"){ -const err496 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_id",schemaPath:"#/properties/capabilities/items/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err496]; -} -else { -vErrors.push(err496); -} -errors++; -} -} -if(data241.file_issuer_generation !== undefined){ -let data252 = data241.file_issuer_generation; -if(typeof data252 === "string"){ -if(!pattern0.test(data252)){ -const err497 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err497]; -} -else { -vErrors.push(err497); -} -errors++; -} -if(!(formats0.validate(data252))){ -const err498 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err498]; -} -else { -vErrors.push(err498); -} -errors++; -} -} -else { -const err499 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err499]; -} -else { -vErrors.push(err499); -} -errors++; -} -} -if(data241.mcp !== undefined){ -let data253 = data241.mcp; -if((data253 !== null) && (!(Array.isArray(data253)))){ -const err500 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp",schemaPath:"#/properties/capabilities/items/properties/mcp/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err500]; -} -else { -vErrors.push(err500); -} -errors++; -} -if(Array.isArray(data253)){ -const len20 = data253.length; -for(let i20=0; i20<len20; i20++){ -let data254 = data253[i20]; -if(data254 && typeof data254 == "object" && !Array.isArray(data254)){ -if(data254.server === undefined){ -const err501 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err501]; -} -else { -vErrors.push(err501); -} -errors++; -} -if(data254.tool === undefined){ -const err502 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err502]; -} -else { -vErrors.push(err502); -} -errors++; -} -if(data254.definition === undefined){ -const err503 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err503]; -} -else { -vErrors.push(err503); -} -errors++; -} -for(const key37 in data254){ -if(!(((key37 === "server") || (key37 === "tool")) || (key37 === "definition"))){ -const err504 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key37},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err504]; -} -else { -vErrors.push(err504); -} -errors++; -} -} -if(data254.server !== undefined){ -if(typeof data254.server !== "string"){ -const err505 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/server",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err505]; -} -else { -vErrors.push(err505); -} -errors++; -} -} -if(data254.tool !== undefined){ -if(typeof data254.tool !== "string"){ -const err506 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/tool",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err506]; -} -else { -vErrors.push(err506); -} -errors++; -} -} -if(data254.definition !== undefined){ -if(typeof data254.definition !== "string"){ -const err507 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/definition",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err507]; -} -else { -vErrors.push(err507); -} -errors++; -} -} -} -else { -const err508 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err508]; -} -else { -vErrors.push(err508); -} -errors++; -} -} -} -} -if(data241.mcp_all !== undefined){ -if(typeof data241.mcp_all !== "boolean"){ -const err509 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp_all",schemaPath:"#/properties/capabilities/items/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err509]; -} -else { -vErrors.push(err509); -} -errors++; -} -} -if(data241.browser !== undefined){ -let data259 = data241.browser; -if((data259 !== null) && (!(data259 && typeof data259 == "object" && !Array.isArray(data259)))){ -const err510 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err510]; -} -else { -vErrors.push(err510); -} -errors++; -} -if(data259 && typeof data259 == "object" && !Array.isArray(data259)){ -if(data259.provider_id === undefined){ -const err511 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err511]; -} -else { -vErrors.push(err511); -} -errors++; -} -if(data259.provider_epoch === undefined){ -const err512 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err512]; -} -else { -vErrors.push(err512); -} -errors++; -} -if(data259.tab_id === undefined){ -const err513 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err513]; -} -else { -vErrors.push(err513); -} -errors++; -} -if(data259.tab_generation === undefined){ -const err514 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err514]; -} -else { -vErrors.push(err514); -} -errors++; -} -if(data259.profile_id === undefined){ -const err515 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err515]; -} -else { -vErrors.push(err515); -} -errors++; -} -if(data259.rights === undefined){ -const err516 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err516]; -} -else { -vErrors.push(err516); -} -errors++; -} -for(const key38 in data259){ -if(!(func2.call(schema160.properties.capabilities.items.properties.browser.properties, key38))){ -const err517 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key38},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err517]; -} -else { -vErrors.push(err517); -} -errors++; -} -} -if(data259.provider_id !== undefined){ -if(typeof data259.provider_id !== "string"){ -const err518 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/provider_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err518]; -} -else { -vErrors.push(err518); -} -errors++; -} -} -if(data259.provider_epoch !== undefined){ -if(typeof data259.provider_epoch !== "string"){ -const err519 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/provider_epoch",schemaPath:"#/properties/capabilities/items/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err519]; -} -else { -vErrors.push(err519); -} -errors++; -} -} -if(data259.tab_id !== undefined){ -if(typeof data259.tab_id !== "string"){ -const err520 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/tab_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err520]; -} -else { -vErrors.push(err520); -} -errors++; -} -} -if(data259.tab_generation !== undefined){ -if(typeof data259.tab_generation !== "string"){ -const err521 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/tab_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err521]; -} -else { -vErrors.push(err521); -} -errors++; -} -} -if(data259.profile_id !== undefined){ -if(typeof data259.profile_id !== "string"){ -const err522 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/profile_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err522]; -} -else { -vErrors.push(err522); -} -errors++; -} -} -if(data259.attachment_id !== undefined){ -if(typeof data259.attachment_id !== "string"){ -const err523 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/attachment_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err523]; -} -else { -vErrors.push(err523); -} -errors++; -} -} -if(data259.attachment_generation !== undefined){ -if(typeof data259.attachment_generation !== "string"){ -const err524 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/attachment_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err524]; -} -else { -vErrors.push(err524); -} -errors++; -} -} -if(data259.rights !== undefined){ -let data267 = data259.rights; -if((data267 !== null) && (!(Array.isArray(data267)))){ -const err525 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/rights",schemaPath:"#/properties/capabilities/items/properties/browser/properties/rights/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err525]; -} -else { -vErrors.push(err525); -} -errors++; -} -if(Array.isArray(data267)){ -const len21 = data267.length; -for(let i21=0; i21<len21; i21++){ -if(typeof data267[i21] !== "string"){ -const err526 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/rights/" + i21,schemaPath:"#/properties/capabilities/items/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err526]; -} -else { -vErrors.push(err526); -} -errors++; -} -} -} -} -if(data259.preview !== undefined){ -let data269 = data259.preview; -if((data269 !== null) && (!(data269 && typeof data269 == "object" && !Array.isArray(data269)))){ -const err527 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err527]; -} -else { -vErrors.push(err527); -} -errors++; -} -if(data269 && typeof data269 == "object" && !Array.isArray(data269)){ -if(data269.host_id === undefined){ -const err528 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err528]; -} -else { -vErrors.push(err528); -} -errors++; -} -if(data269.host_identity === undefined){ -const err529 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err529]; -} -else { -vErrors.push(err529); -} -errors++; -} -if(data269.connection_generation === undefined){ -const err530 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err530]; -} -else { -vErrors.push(err530); -} -errors++; -} -if(data269.environment_id === undefined){ -const err531 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err531]; -} -else { -vErrors.push(err531); -} -errors++; -} -if(data269.loopback === undefined){ -const err532 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err532]; -} -else { -vErrors.push(err532); -} -errors++; -} -if(data269.ports === undefined){ -const err533 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err533]; -} -else { -vErrors.push(err533); -} -errors++; -} -for(const key39 in data269){ -if(!((((((key39 === "host_id") || (key39 === "host_identity")) || (key39 === "connection_generation")) || (key39 === "environment_id")) || (key39 === "loopback")) || (key39 === "ports"))){ -const err534 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key39},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err534]; -} -else { -vErrors.push(err534); -} -errors++; -} -} -if(data269.host_id !== undefined){ -if(typeof data269.host_id !== "string"){ -const err535 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/host_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err535]; -} -else { -vErrors.push(err535); -} -errors++; -} -} -if(data269.host_identity !== undefined){ -if(typeof data269.host_identity !== "string"){ -const err536 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/host_identity",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err536]; -} -else { -vErrors.push(err536); -} -errors++; -} -} -if(data269.connection_generation !== undefined){ -if(typeof data269.connection_generation !== "string"){ -const err537 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/connection_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err537]; -} -else { -vErrors.push(err537); -} -errors++; -} -} -if(data269.environment_id !== undefined){ -if(typeof data269.environment_id !== "string"){ -const err538 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/environment_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err538]; -} -else { -vErrors.push(err538); -} -errors++; -} -} -if(data269.loopback !== undefined){ -if(typeof data269.loopback !== "string"){ -const err539 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/loopback",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err539]; -} -else { -vErrors.push(err539); -} -errors++; -} -} -if(data269.ports !== undefined){ -let data275 = data269.ports; -if((data275 !== null) && (!(Array.isArray(data275)))){ -const err540 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/ports",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err540]; -} -else { -vErrors.push(err540); -} -errors++; -} -if(Array.isArray(data275)){ -const len22 = data275.length; -for(let i22=0; i22<len22; i22++){ -let data276 = data275[i22]; -if(!((typeof data276 == "number") && (!(data276 % 1) && !isNaN(data276)))){ -const err541 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/ports/" + i22,schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err541]; -} -else { -vErrors.push(err541); -} -errors++; -} -} -} -} -} -} -} -} -if(data241.browser_issuer_id !== undefined){ -if(typeof data241.browser_issuer_id !== "string"){ -const err542 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_issuer_id",schemaPath:"#/properties/capabilities/items/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err542]; -} -else { -vErrors.push(err542); -} -errors++; -} -} -if(data241.browser_issuer_generation !== undefined){ -let data278 = data241.browser_issuer_generation; -if(!((typeof data278 == "number") && (!(data278 % 1) && !isNaN(data278)))){ -const err543 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err543]; -} -else { -vErrors.push(err543); -} -errors++; -} -} -if(data241.browser_delegation_only !== undefined){ -if(typeof data241.browser_delegation_only !== "boolean"){ -const err544 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_delegation_only",schemaPath:"#/properties/capabilities/items/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err544]; -} -else { -vErrors.push(err544); -} -errors++; -} -} -if(data241.generation !== undefined){ -let data280 = data241.generation; -if(typeof data280 === "string"){ -if(!pattern0.test(data280)){ -const err545 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err545]; -} -else { -vErrors.push(err545); -} -errors++; -} -if(!(formats0.validate(data280))){ -const err546 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err546]; -} -else { -vErrors.push(err546); -} -errors++; -} -} -else { -const err547 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err547]; -} -else { -vErrors.push(err547); -} -errors++; -} -} -if(data241.status !== undefined){ -if(typeof data241.status !== "string"){ -const err548 = {instancePath:instancePath+"/capabilities/" + i17+"/status",schemaPath:"#/properties/capabilities/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err548]; -} -else { -vErrors.push(err548); -} -errors++; -} -} -if(data241.expires_at !== undefined){ -if(typeof data241.expires_at !== "string"){ -const err549 = {instancePath:instancePath+"/capabilities/" + i17+"/expires_at",schemaPath:"#/properties/capabilities/items/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err549]; -} -else { -vErrors.push(err549); -} -errors++; -} -} -if(data241.created_at !== undefined){ -if(typeof data241.created_at !== "string"){ -const err550 = {instancePath:instancePath+"/capabilities/" + i17+"/created_at",schemaPath:"#/properties/capabilities/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err550]; -} -else { -vErrors.push(err550); -} -errors++; -} -} -if(data241.updated_at !== undefined){ -if(typeof data241.updated_at !== "string"){ -const err551 = {instancePath:instancePath+"/capabilities/" + i17+"/updated_at",schemaPath:"#/properties/capabilities/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err551]; -} -else { -vErrors.push(err551); -} -errors++; -} -} -} -else { -const err552 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err552]; -} -else { -vErrors.push(err552); -} -errors++; -} -} -} -} -if(data.schedules !== undefined){ -let data285 = data.schedules; -if((data285 !== null) && (!(Array.isArray(data285)))){ -const err553 = {instancePath:instancePath+"/schedules",schemaPath:"#/properties/schedules/type",keyword:"type",params:{type: schema160.properties.schedules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err553]; -} -else { -vErrors.push(err553); -} -errors++; -} -if(Array.isArray(data285)){ -const len23 = data285.length; -for(let i23=0; i23<len23; i23++){ -let data286 = data285[i23]; -if(data286 && typeof data286 == "object" && !Array.isArray(data286)){ -if(data286.id === undefined){ -const err554 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err554]; -} -else { -vErrors.push(err554); -} -errors++; -} -if(data286.schedule === undefined){ -const err555 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err555]; -} -else { -vErrors.push(err555); -} -errors++; -} -if(data286.prompt === undefined){ -const err556 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err556]; -} -else { -vErrors.push(err556); -} -errors++; -} -if(data286.anchor === undefined){ -const err557 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err557]; -} -else { -vErrors.push(err557); -} -errors++; -} -if(data286.last_fire === undefined){ -const err558 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err558]; -} -else { -vErrors.push(err558); -} -errors++; -} -for(const key40 in data286){ -if(!(((((key40 === "id") || (key40 === "schedule")) || (key40 === "prompt")) || (key40 === "anchor")) || (key40 === "last_fire"))){ -const err559 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key40},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err559]; -} -else { -vErrors.push(err559); -} -errors++; -} -} -if(data286.id !== undefined){ -let data287 = data286.id; -if(!((typeof data287 == "number") && (!(data287 % 1) && !isNaN(data287)))){ -const err560 = {instancePath:instancePath+"/schedules/" + i23+"/id",schemaPath:"#/properties/schedules/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err560]; -} -else { -vErrors.push(err560); -} -errors++; -} -} -if(data286.schedule !== undefined){ -if(typeof data286.schedule !== "string"){ -const err561 = {instancePath:instancePath+"/schedules/" + i23+"/schedule",schemaPath:"#/properties/schedules/items/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err561]; -} -else { -vErrors.push(err561); -} -errors++; -} -} -if(data286.prompt !== undefined){ -if(typeof data286.prompt !== "string"){ -const err562 = {instancePath:instancePath+"/schedules/" + i23+"/prompt",schemaPath:"#/properties/schedules/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err562]; -} -else { -vErrors.push(err562); -} -errors++; -} -} -if(data286.anchor !== undefined){ -if(typeof data286.anchor !== "string"){ -const err563 = {instancePath:instancePath+"/schedules/" + i23+"/anchor",schemaPath:"#/properties/schedules/items/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err563]; -} -else { -vErrors.push(err563); -} -errors++; -} -} -if(data286.last_fire !== undefined){ -if(typeof data286.last_fire !== "string"){ -const err564 = {instancePath:instancePath+"/schedules/" + i23+"/last_fire",schemaPath:"#/properties/schedules/items/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err564]; -} -else { -vErrors.push(err564); -} -errors++; -} -} -} -else { -const err565 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err565]; -} -else { -vErrors.push(err565); -} -errors++; -} -} -} -} -if(data.upcoming_schedules !== undefined){ -let data292 = data.upcoming_schedules; -if((data292 !== null) && (!(Array.isArray(data292)))){ -const err566 = {instancePath:instancePath+"/upcoming_schedules",schemaPath:"#/properties/upcoming_schedules/type",keyword:"type",params:{type: schema160.properties.upcoming_schedules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err566]; -} -else { -vErrors.push(err566); -} -errors++; -} -if(Array.isArray(data292)){ -const len24 = data292.length; -for(let i24=0; i24<len24; i24++){ -let data293 = data292[i24]; -if(data293 && typeof data293 == "object" && !Array.isArray(data293)){ -if(data293.id === undefined){ -const err567 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err567]; -} -else { -vErrors.push(err567); -} -errors++; -} -if(data293.next_fire === undefined){ -const err568 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "next_fire"},message:"must have required property '"+"next_fire"+"'"}; -if(vErrors === null){ -vErrors = [err568]; -} -else { -vErrors.push(err568); -} -errors++; -} -if(data293.prompt === undefined){ -const err569 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err569]; -} -else { -vErrors.push(err569); -} -errors++; -} -for(const key41 in data293){ -if(!((((key41 === "id") || (key41 === "next_fire")) || (key41 === "prompt")) || (key41 === "prompt_truncated"))){ -const err570 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key41},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err570]; -} -else { -vErrors.push(err570); -} -errors++; -} -} -if(data293.id !== undefined){ -let data294 = data293.id; -if(!((typeof data294 == "number") && (!(data294 % 1) && !isNaN(data294)))){ -const err571 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/id",schemaPath:"#/properties/upcoming_schedules/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err571]; -} -else { -vErrors.push(err571); -} -errors++; -} -} -if(data293.next_fire !== undefined){ -if(typeof data293.next_fire !== "string"){ -const err572 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/next_fire",schemaPath:"#/properties/upcoming_schedules/items/properties/next_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err572]; -} -else { -vErrors.push(err572); -} -errors++; -} -} -if(data293.prompt !== undefined){ -if(typeof data293.prompt !== "string"){ -const err573 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/prompt",schemaPath:"#/properties/upcoming_schedules/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err573]; -} -else { -vErrors.push(err573); -} -errors++; -} -} -if(data293.prompt_truncated !== undefined){ -if(typeof data293.prompt_truncated !== "boolean"){ -const err574 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/prompt_truncated",schemaPath:"#/properties/upcoming_schedules/items/properties/prompt_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err574]; -} -else { -vErrors.push(err574); -} -errors++; -} -} -} -else { -const err575 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err575]; -} -else { -vErrors.push(err575); -} -errors++; -} -} -} -} -if(data.upcoming_schedule_count !== undefined){ -let data298 = data.upcoming_schedule_count; -if((data298 !== null) && (!((typeof data298 == "number") && (!(data298 % 1) && !isNaN(data298))))){ -const err576 = {instancePath:instancePath+"/upcoming_schedule_count",schemaPath:"#/properties/upcoming_schedule_count/type",keyword:"type",params:{type: schema160.properties.upcoming_schedule_count.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err576]; -} -else { -vErrors.push(err576); -} -errors++; -} -} -if(data.permissions !== undefined){ -let data299 = data.permissions; -if((data299 !== null) && (!(Array.isArray(data299)))){ -const err577 = {instancePath:instancePath+"/permissions",schemaPath:"#/properties/permissions/type",keyword:"type",params:{type: schema160.properties.permissions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err577]; -} -else { -vErrors.push(err577); -} -errors++; -} -if(Array.isArray(data299)){ -const len25 = data299.length; -for(let i25=0; i25<len25; i25++){ -let data300 = data299[i25]; -if(data300 && typeof data300 == "object" && !Array.isArray(data300)){ -if(data300.id === undefined){ -const err578 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err578]; -} -else { -vErrors.push(err578); -} -errors++; -} -if(data300.agent_id === undefined){ -const err579 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err579]; -} -else { -vErrors.push(err579); -} -errors++; -} -if(data300.operation_id === undefined){ -const err580 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err580]; -} -else { -vErrors.push(err580); -} -errors++; -} -if(data300.operation === undefined){ -const err581 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err581]; -} -else { -vErrors.push(err581); -} -errors++; -} -if(data300.canonical_path === undefined){ -const err582 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err582]; -} -else { -vErrors.push(err582); -} -errors++; -} -if(data300.request_digest === undefined){ -const err583 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err583]; -} -else { -vErrors.push(err583); -} -errors++; -} -if(data300.capability_id === undefined){ -const err584 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err584]; -} -else { -vErrors.push(err584); -} -errors++; -} -if(data300.capability_generation === undefined){ -const err585 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err585]; -} -else { -vErrors.push(err585); -} -errors++; -} -if(data300.status === undefined){ -const err586 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err586]; -} -else { -vErrors.push(err586); -} -errors++; -} -if(data300.command === undefined){ -const err587 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err587]; -} -else { -vErrors.push(err587); -} -errors++; -} -if(data300.rule === undefined){ -const err588 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err588]; -} -else { -vErrors.push(err588); -} -errors++; -} -for(const key42 in data300){ -if(!(func2.call(schema160.properties.permissions.items.properties, key42))){ -const err589 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key42},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err589]; -} -else { -vErrors.push(err589); -} -errors++; -} -} -if(data300.id !== undefined){ -if(typeof data300.id !== "string"){ -const err590 = {instancePath:instancePath+"/permissions/" + i25+"/id",schemaPath:"#/properties/permissions/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err590]; -} -else { -vErrors.push(err590); -} -errors++; -} -} -if(data300.agent_id !== undefined){ -if(typeof data300.agent_id !== "string"){ -const err591 = {instancePath:instancePath+"/permissions/" + i25+"/agent_id",schemaPath:"#/properties/permissions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err591]; -} -else { -vErrors.push(err591); -} -errors++; -} -} -if(data300.operation_id !== undefined){ -if(typeof data300.operation_id !== "string"){ -const err592 = {instancePath:instancePath+"/permissions/" + i25+"/operation_id",schemaPath:"#/properties/permissions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err592]; -} -else { -vErrors.push(err592); -} -errors++; -} -} -if(data300.operation !== undefined){ -if(typeof data300.operation !== "string"){ -const err593 = {instancePath:instancePath+"/permissions/" + i25+"/operation",schemaPath:"#/properties/permissions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err593]; -} -else { -vErrors.push(err593); -} -errors++; -} -} -if(data300.canonical_path !== undefined){ -if(typeof data300.canonical_path !== "string"){ -const err594 = {instancePath:instancePath+"/permissions/" + i25+"/canonical_path",schemaPath:"#/properties/permissions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err594]; -} -else { -vErrors.push(err594); -} -errors++; -} -} -if(data300.request_digest !== undefined){ -if(typeof data300.request_digest !== "string"){ -const err595 = {instancePath:instancePath+"/permissions/" + i25+"/request_digest",schemaPath:"#/properties/permissions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err595]; -} -else { -vErrors.push(err595); -} -errors++; -} -} -if(data300.capability_id !== undefined){ -if(typeof data300.capability_id !== "string"){ -const err596 = {instancePath:instancePath+"/permissions/" + i25+"/capability_id",schemaPath:"#/properties/permissions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err596]; -} -else { -vErrors.push(err596); -} -errors++; -} -} -if(data300.capability_generation !== undefined){ -let data308 = data300.capability_generation; -if(typeof data308 === "string"){ -if(!pattern0.test(data308)){ -const err597 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err597]; -} -else { -vErrors.push(err597); -} -errors++; -} -if(!(formats0.validate(data308))){ -const err598 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err598]; -} -else { -vErrors.push(err598); -} -errors++; -} -} -else { -const err599 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err599]; -} -else { -vErrors.push(err599); -} -errors++; -} -} -if(data300.status !== undefined){ -if(typeof data300.status !== "string"){ -const err600 = {instancePath:instancePath+"/permissions/" + i25+"/status",schemaPath:"#/properties/permissions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err600]; -} -else { -vErrors.push(err600); -} -errors++; -} -} -if(data300.command !== undefined){ -if(typeof data300.command !== "string"){ -const err601 = {instancePath:instancePath+"/permissions/" + i25+"/command",schemaPath:"#/properties/permissions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err601]; -} -else { -vErrors.push(err601); -} -errors++; -} -} -if(data300.rule !== undefined){ -if(typeof data300.rule !== "string"){ -const err602 = {instancePath:instancePath+"/permissions/" + i25+"/rule",schemaPath:"#/properties/permissions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err602]; -} -else { -vErrors.push(err602); -} -errors++; -} -} -} -else { -const err603 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err603]; -} -else { -vErrors.push(err603); -} -errors++; -} -} -} -} -if(data.questions !== undefined){ -let data312 = data.questions; -if((data312 !== null) && (!(Array.isArray(data312)))){ -const err604 = {instancePath:instancePath+"/questions",schemaPath:"#/properties/questions/type",keyword:"type",params:{type: schema160.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err604]; -} -else { -vErrors.push(err604); -} -errors++; -} -if(Array.isArray(data312)){ -const len26 = data312.length; -for(let i26=0; i26<len26; i26++){ -let data313 = data312[i26]; -if(data313 && typeof data313 == "object" && !Array.isArray(data313)){ -for(const key43 in data313){ -if(!(func2.call(schema160.properties.questions.items.properties, key43))){ -const err605 = {instancePath:instancePath+"/questions/" + i26,schemaPath:"#/properties/questions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key43},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err605]; -} -else { -vErrors.push(err605); -} -errors++; -} -} -if(data313.turn_id !== undefined){ -if(typeof data313.turn_id !== "string"){ -const err606 = {instancePath:instancePath+"/questions/" + i26+"/turn_id",schemaPath:"#/properties/questions/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err606]; -} -else { -vErrors.push(err606); -} -errors++; -} -} -if(data313.root_id !== undefined){ -if(typeof data313.root_id !== "string"){ -const err607 = {instancePath:instancePath+"/questions/" + i26+"/root_id",schemaPath:"#/properties/questions/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err607]; -} -else { -vErrors.push(err607); -} -errors++; -} -} -if(data313.agent_id !== undefined){ -if(typeof data313.agent_id !== "string"){ -const err608 = {instancePath:instancePath+"/questions/" + i26+"/agent_id",schemaPath:"#/properties/questions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err608]; -} -else { -vErrors.push(err608); -} -errors++; -} -} -if(data313.sender_agent_id !== undefined){ -if(typeof data313.sender_agent_id !== "string"){ -const err609 = {instancePath:instancePath+"/questions/" + i26+"/sender_agent_id",schemaPath:"#/properties/questions/items/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err609]; -} -else { -vErrors.push(err609); -} -errors++; -} -} -if(data313.inbox_seq !== undefined){ -let data318 = data313.inbox_seq; -if(typeof data318 === "string"){ -if(!pattern0.test(data318)){ -const err610 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err610]; -} -else { -vErrors.push(err610); -} -errors++; -} -if(!(formats0.validate(data318))){ -const err611 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err611]; -} -else { -vErrors.push(err611); -} -errors++; -} -} -else { -const err612 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err612]; -} -else { -vErrors.push(err612); -} -errors++; -} -} -if(data313.inbox_kind !== undefined){ -if(typeof data313.inbox_kind !== "string"){ -const err613 = {instancePath:instancePath+"/questions/" + i26+"/inbox_kind",schemaPath:"#/properties/questions/items/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err613]; -} -else { -vErrors.push(err613); -} -errors++; -} -} -if(data313.delivery !== undefined){ -if(typeof data313.delivery !== "string"){ -const err614 = {instancePath:instancePath+"/questions/" + i26+"/delivery",schemaPath:"#/properties/questions/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err614]; -} -else { -vErrors.push(err614); -} -errors++; -} -} -if(data313.message_id !== undefined){ -if(typeof data313.message_id !== "string"){ -const err615 = {instancePath:instancePath+"/questions/" + i26+"/message_id",schemaPath:"#/properties/questions/items/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err615]; -} -else { -vErrors.push(err615); -} -errors++; -} -} -if(data313.phase !== undefined){ -if(typeof data313.phase !== "string"){ -const err616 = {instancePath:instancePath+"/questions/" + i26+"/phase",schemaPath:"#/properties/questions/items/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err616]; -} -else { -vErrors.push(err616); -} -errors++; -} -} -if(data313.status !== undefined){ -if(typeof data313.status !== "string"){ -const err617 = {instancePath:instancePath+"/questions/" + i26+"/status",schemaPath:"#/properties/questions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err617]; -} -else { -vErrors.push(err617); -} -errors++; -} -} -if(data313.terminal_cause !== undefined){ -if(typeof data313.terminal_cause !== "string"){ -const err618 = {instancePath:instancePath+"/questions/" + i26+"/terminal_cause",schemaPath:"#/properties/questions/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err618]; -} -else { -vErrors.push(err618); -} -errors++; -} -} -if(data313.command_client_id !== undefined){ -if(typeof data313.command_client_id !== "string"){ -const err619 = {instancePath:instancePath+"/questions/" + i26+"/command_client_id",schemaPath:"#/properties/questions/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err619]; -} -else { -vErrors.push(err619); -} -errors++; -} -} -if(data313.command_id !== undefined){ -if(typeof data313.command_id !== "string"){ -const err620 = {instancePath:instancePath+"/questions/" + i26+"/command_id",schemaPath:"#/properties/questions/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err620]; -} -else { -vErrors.push(err620); -} -errors++; -} -} -if(data313.operation_id !== undefined){ -if(typeof data313.operation_id !== "string"){ -const err621 = {instancePath:instancePath+"/questions/" + i26+"/operation_id",schemaPath:"#/properties/questions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err621]; -} -else { -vErrors.push(err621); -} -errors++; -} -} -if(data313.trace_id !== undefined){ -if(typeof data313.trace_id !== "string"){ -const err622 = {instancePath:instancePath+"/questions/" + i26+"/trace_id",schemaPath:"#/properties/questions/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err622]; -} -else { -vErrors.push(err622); -} -errors++; -} -} -if(data313.schedule_id !== undefined){ -let data329 = data313.schedule_id; -if(!((typeof data329 == "number") && (!(data329 % 1) && !isNaN(data329)))){ -const err623 = {instancePath:instancePath+"/questions/" + i26+"/schedule_id",schemaPath:"#/properties/questions/items/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err623]; -} -else { -vErrors.push(err623); -} -errors++; -} -} -if(data313.slot !== undefined){ -if(typeof data313.slot !== "string"){ -const err624 = {instancePath:instancePath+"/questions/" + i26+"/slot",schemaPath:"#/properties/questions/items/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err624]; -} -else { -vErrors.push(err624); -} -errors++; -} -} -if(data313.error !== undefined){ -if(typeof data313.error !== "string"){ -const err625 = {instancePath:instancePath+"/questions/" + i26+"/error",schemaPath:"#/properties/questions/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err625]; -} -else { -vErrors.push(err625); -} -errors++; -} -} -if(data313.model_call !== undefined){ -let data332 = data313.model_call; -if((data332 !== null) && (!(data332 && typeof data332 == "object" && !Array.isArray(data332)))){ -const err626 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err626]; -} -else { -vErrors.push(err626); -} -errors++; -} -if(data332 && typeof data332 == "object" && !Array.isArray(data332)){ -if(data332.id === undefined){ -const err627 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err627]; -} -else { -vErrors.push(err627); -} -errors++; -} -if(data332.logical_id === undefined){ -const err628 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err628]; -} -else { -vErrors.push(err628); -} -errors++; -} -if(data332.number === undefined){ -const err629 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err629]; -} -else { -vErrors.push(err629); -} -errors++; -} -if(data332.purpose === undefined){ -const err630 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err630]; -} -else { -vErrors.push(err630); -} -errors++; -} -if(data332.usage_source === undefined){ -const err631 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err631]; -} -else { -vErrors.push(err631); -} -errors++; -} -if(data332.cost_source === undefined){ -const err632 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err632]; -} -else { -vErrors.push(err632); -} -errors++; -} -if(data332.tokens === undefined){ -const err633 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err633]; -} -else { -vErrors.push(err633); -} -errors++; -} -if(data332.cost_micros === undefined){ -const err634 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err634]; -} -else { -vErrors.push(err634); -} -errors++; -} -if(data332.elapsed_millis === undefined){ -const err635 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err635]; -} -else { -vErrors.push(err635); -} -errors++; -} -if(data332.exhausted === undefined){ -const err636 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err636]; -} -else { -vErrors.push(err636); -} -errors++; -} -for(const key44 in data332){ -if(!(func2.call(schema160.properties.questions.items.properties.model_call.properties, key44))){ -const err637 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key44},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err637]; -} -else { -vErrors.push(err637); -} -errors++; -} -} -if(data332.id !== undefined){ -if(typeof data332.id !== "string"){ -const err638 = {instancePath:instancePath+"/questions/" + i26+"/model_call/id",schemaPath:"#/properties/questions/items/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err638]; -} -else { -vErrors.push(err638); -} -errors++; -} -} -if(data332.logical_id !== undefined){ -if(typeof data332.logical_id !== "string"){ -const err639 = {instancePath:instancePath+"/questions/" + i26+"/model_call/logical_id",schemaPath:"#/properties/questions/items/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err639]; -} -else { -vErrors.push(err639); -} -errors++; -} -} -if(data332.number !== undefined){ -let data335 = data332.number; -if(!((typeof data335 == "number") && (!(data335 % 1) && !isNaN(data335)))){ -const err640 = {instancePath:instancePath+"/questions/" + i26+"/model_call/number",schemaPath:"#/properties/questions/items/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err640]; -} -else { -vErrors.push(err640); -} -errors++; -} -} -if(data332.purpose !== undefined){ -if(typeof data332.purpose !== "string"){ -const err641 = {instancePath:instancePath+"/questions/" + i26+"/model_call/purpose",schemaPath:"#/properties/questions/items/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err641]; -} -else { -vErrors.push(err641); -} -errors++; -} -} -if(data332.usage_source !== undefined){ -if(typeof data332.usage_source !== "string"){ -const err642 = {instancePath:instancePath+"/questions/" + i26+"/model_call/usage_source",schemaPath:"#/properties/questions/items/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err642]; -} -else { -vErrors.push(err642); -} -errors++; -} -} -if(data332.cost_source !== undefined){ -if(typeof data332.cost_source !== "string"){ -const err643 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_source",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err643]; -} -else { -vErrors.push(err643); -} -errors++; -} -} -if(data332.tokens !== undefined){ -let data339 = data332.tokens; -if(typeof data339 === "string"){ -if(!pattern0.test(data339)){ -const err644 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err644]; -} -else { -vErrors.push(err644); -} -errors++; -} -if(!(formats0.validate(data339))){ -const err645 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err645]; -} -else { -vErrors.push(err645); -} -errors++; -} -} -else { -const err646 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err646]; -} -else { -vErrors.push(err646); -} -errors++; -} -} -if(data332.cost_micros !== undefined){ -let data340 = data332.cost_micros; -if(typeof data340 === "string"){ -if(!pattern0.test(data340)){ -const err647 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err647]; -} -else { -vErrors.push(err647); -} -errors++; -} -if(!(formats0.validate(data340))){ -const err648 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err648]; -} -else { -vErrors.push(err648); -} -errors++; -} -} -else { -const err649 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err649]; -} -else { -vErrors.push(err649); -} -errors++; -} -} -if(data332.elapsed_millis !== undefined){ -let data341 = data332.elapsed_millis; -if(typeof data341 === "string"){ -if(!pattern0.test(data341)){ -const err650 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err650]; -} -else { -vErrors.push(err650); -} -errors++; -} -if(!(formats0.validate(data341))){ -const err651 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err651]; -} -else { -vErrors.push(err651); -} -errors++; -} -} -else { -const err652 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err652]; -} -else { -vErrors.push(err652); -} -errors++; -} -} -if(data332.exhausted !== undefined){ -if(typeof data332.exhausted !== "boolean"){ -const err653 = {instancePath:instancePath+"/questions/" + i26+"/model_call/exhausted",schemaPath:"#/properties/questions/items/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err653]; -} -else { -vErrors.push(err653); -} -errors++; -} -} -} -} -if(data313.acknowledged_inbox !== undefined){ -let data343 = data313.acknowledged_inbox; -if(Array.isArray(data343)){ -const len27 = data343.length; -for(let i27=0; i27<len27; i27++){ -let data344 = data343[i27]; -if(typeof data344 === "string"){ -if(!pattern0.test(data344)){ -const err654 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err654]; -} -else { -vErrors.push(err654); -} -errors++; -} -if(!(formats0.validate(data344))){ -const err655 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err655]; -} -else { -vErrors.push(err655); -} -errors++; -} -} -else { -const err656 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err656]; -} -else { -vErrors.push(err656); -} -errors++; -} -} -} -else { -const err657 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox",schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err657]; -} -else { -vErrors.push(err657); -} -errors++; -} -} -if(data313.subscription_id !== undefined){ -if(typeof data313.subscription_id !== "string"){ -const err658 = {instancePath:instancePath+"/questions/" + i26+"/subscription_id",schemaPath:"#/properties/questions/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err658]; -} -else { -vErrors.push(err658); -} -errors++; -} -} -if(data313.key !== undefined){ -if(typeof data313.key !== "string"){ -const err659 = {instancePath:instancePath+"/questions/" + i26+"/key",schemaPath:"#/properties/questions/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err659]; -} -else { -vErrors.push(err659); -} -errors++; -} -} -if(data313.version !== undefined){ -let data347 = data313.version; -if(typeof data347 === "string"){ -if(!pattern0.test(data347)){ -const err660 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err660]; -} -else { -vErrors.push(err660); -} -errors++; -} -if(!(formats0.validate(data347))){ -const err661 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err661]; -} -else { -vErrors.push(err661); -} -errors++; -} -} -else { -const err662 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err662]; -} -else { -vErrors.push(err662); -} -errors++; -} -} -if(data313.expected_version !== undefined){ -let data348 = data313.expected_version; -if(typeof data348 === "string"){ -if(!pattern0.test(data348)){ -const err663 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err663]; -} -else { -vErrors.push(err663); -} -errors++; -} -if(!(formats0.validate(data348))){ -const err664 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err664]; -} -else { -vErrors.push(err664); -} -errors++; -} -} -else { -const err665 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err665]; -} -else { -vErrors.push(err665); -} -errors++; -} -} -if(data313.restored !== undefined){ -let data349 = data313.restored; -if((data349 !== null) && (!(Array.isArray(data349)))){ -const err666 = {instancePath:instancePath+"/questions/" + i26+"/restored",schemaPath:"#/properties/questions/items/properties/restored/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err666]; -} -else { -vErrors.push(err666); -} -errors++; -} -if(Array.isArray(data349)){ -const len28 = data349.length; -for(let i28=0; i28<len28; i28++){ -if(typeof data349[i28] !== "string"){ -const err667 = {instancePath:instancePath+"/questions/" + i26+"/restored/" + i28,schemaPath:"#/properties/questions/items/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err667]; -} -else { -vErrors.push(err667); -} -errors++; -} -} -} -} -if(data313.not_restored !== undefined){ -let data351 = data313.not_restored; -if((data351 !== null) && (!(Array.isArray(data351)))){ -const err668 = {instancePath:instancePath+"/questions/" + i26+"/not_restored",schemaPath:"#/properties/questions/items/properties/not_restored/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err668]; -} -else { -vErrors.push(err668); -} -errors++; -} -if(Array.isArray(data351)){ -const len29 = data351.length; -for(let i29=0; i29<len29; i29++){ -let data352 = data351[i29]; -if(data352 && typeof data352 == "object" && !Array.isArray(data352)){ -if(data352.name === undefined){ -const err669 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err669]; -} -else { -vErrors.push(err669); -} -errors++; -} -if(data352.reason === undefined){ -const err670 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err670]; -} -else { -vErrors.push(err670); -} -errors++; -} -for(const key45 in data352){ -if(!((key45 === "name") || (key45 === "reason"))){ -const err671 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key45},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err671]; -} -else { -vErrors.push(err671); -} -errors++; -} -} -if(data352.name !== undefined){ -if(typeof data352.name !== "string"){ -const err672 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29+"/name",schemaPath:"#/properties/questions/items/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err672]; -} -else { -vErrors.push(err672); -} -errors++; -} -} -if(data352.reason !== undefined){ -if(typeof data352.reason !== "string"){ -const err673 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29+"/reason",schemaPath:"#/properties/questions/items/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err673]; -} -else { -vErrors.push(err673); -} -errors++; -} -} -} -else { -const err674 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err674]; -} -else { -vErrors.push(err674); -} -errors++; -} -} -} -} -if(data313.attempt !== undefined){ -if(typeof data313.attempt !== "string"){ -const err675 = {instancePath:instancePath+"/questions/" + i26+"/attempt",schemaPath:"#/properties/questions/items/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err675]; -} -else { -vErrors.push(err675); -} -errors++; -} -} -if(data313.budget_kind !== undefined){ -if(typeof data313.budget_kind !== "string"){ -const err676 = {instancePath:instancePath+"/questions/" + i26+"/budget_kind",schemaPath:"#/properties/questions/items/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err676]; -} -else { -vErrors.push(err676); -} -errors++; -} -} -if(data313.amount !== undefined){ -let data357 = data313.amount; -if(typeof data357 === "string"){ -if(!pattern0.test(data357)){ -const err677 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err677]; -} -else { -vErrors.push(err677); -} -errors++; -} -if(!(formats0.validate(data357))){ -const err678 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err678]; -} -else { -vErrors.push(err678); -} -errors++; -} -} -else { -const err679 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err679]; -} -else { -vErrors.push(err679); -} -errors++; -} -} -if(data313.limit !== undefined){ -let data358 = data313.limit; -if(typeof data358 === "string"){ -if(!pattern0.test(data358)){ -const err680 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err680]; -} -else { -vErrors.push(err680); -} -errors++; -} -if(!(formats0.validate(data358))){ -const err681 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err681]; -} -else { -vErrors.push(err681); -} -errors++; -} -} -else { -const err682 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err682]; -} -else { -vErrors.push(err682); -} -errors++; -} -} -if(data313.used !== undefined){ -let data359 = data313.used; -if(typeof data359 === "string"){ -if(!pattern0.test(data359)){ -const err683 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err683]; -} -else { -vErrors.push(err683); -} -errors++; -} -if(!(formats0.validate(data359))){ -const err684 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err684]; -} -else { -vErrors.push(err684); -} -errors++; -} -} -else { -const err685 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err685]; -} -else { -vErrors.push(err685); -} -errors++; -} -} -if(data313.reserved !== undefined){ -let data360 = data313.reserved; -if(typeof data360 === "string"){ -if(!pattern0.test(data360)){ -const err686 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err686]; -} -else { -vErrors.push(err686); -} -errors++; -} -if(!(formats0.validate(data360))){ -const err687 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err687]; -} -else { -vErrors.push(err687); -} -errors++; -} -} -else { -const err688 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err688]; -} -else { -vErrors.push(err688); -} -errors++; -} -} -if(data313.capability_id !== undefined){ -if(typeof data313.capability_id !== "string"){ -const err689 = {instancePath:instancePath+"/questions/" + i26+"/capability_id",schemaPath:"#/properties/questions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err689]; -} -else { -vErrors.push(err689); -} -errors++; -} -} -if(data313.generation !== undefined){ -let data362 = data313.generation; -if(typeof data362 === "string"){ -if(!pattern0.test(data362)){ -const err690 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err690]; -} -else { -vErrors.push(err690); -} -errors++; -} -if(!(formats0.validate(data362))){ -const err691 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err691]; -} -else { -vErrors.push(err691); -} -errors++; -} -} -else { -const err692 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err692]; -} -else { -vErrors.push(err692); -} -errors++; -} -} -if(data313.permission_id !== undefined){ -if(typeof data313.permission_id !== "string"){ -const err693 = {instancePath:instancePath+"/questions/" + i26+"/permission_id",schemaPath:"#/properties/questions/items/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err693]; -} -else { -vErrors.push(err693); -} -errors++; -} -} -if(data313.operation !== undefined){ -if(typeof data313.operation !== "string"){ -const err694 = {instancePath:instancePath+"/questions/" + i26+"/operation",schemaPath:"#/properties/questions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err694]; -} -else { -vErrors.push(err694); -} -errors++; -} -} -if(data313.canonical_path !== undefined){ -if(typeof data313.canonical_path !== "string"){ -const err695 = {instancePath:instancePath+"/questions/" + i26+"/canonical_path",schemaPath:"#/properties/questions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err695]; -} -else { -vErrors.push(err695); -} -errors++; -} -} -if(data313.request_digest !== undefined){ -if(typeof data313.request_digest !== "string"){ -const err696 = {instancePath:instancePath+"/questions/" + i26+"/request_digest",schemaPath:"#/properties/questions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err696]; -} -else { -vErrors.push(err696); -} -errors++; -} -} -if(data313.command !== undefined){ -if(typeof data313.command !== "string"){ -const err697 = {instancePath:instancePath+"/questions/" + i26+"/command",schemaPath:"#/properties/questions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err697]; -} -else { -vErrors.push(err697); -} -errors++; -} -} -if(data313.rule !== undefined){ -if(typeof data313.rule !== "string"){ -const err698 = {instancePath:instancePath+"/questions/" + i26+"/rule",schemaPath:"#/properties/questions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err698]; -} -else { -vErrors.push(err698); -} -errors++; -} -} -if(data313.rule_source !== undefined){ -if(typeof data313.rule_source !== "string"){ -const err699 = {instancePath:instancePath+"/questions/" + i26+"/rule_source",schemaPath:"#/properties/questions/items/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err699]; -} -else { -vErrors.push(err699); -} -errors++; -} -} -if(data313.question_id !== undefined){ -if(typeof data313.question_id !== "string"){ -const err700 = {instancePath:instancePath+"/questions/" + i26+"/question_id",schemaPath:"#/properties/questions/items/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err700]; -} -else { -vErrors.push(err700); -} -errors++; -} -} -if(data313.question !== undefined){ -if(typeof data313.question !== "string"){ -const err701 = {instancePath:instancePath+"/questions/" + i26+"/question",schemaPath:"#/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err701]; -} -else { -vErrors.push(err701); -} -errors++; -} -} -if(data313.options !== undefined){ -let data372 = data313.options; -if((data372 !== null) && (!(Array.isArray(data372)))){ -const err702 = {instancePath:instancePath+"/questions/" + i26+"/options",schemaPath:"#/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err702]; -} -else { -vErrors.push(err702); -} -errors++; -} -if(Array.isArray(data372)){ -const len30 = data372.length; -for(let i30=0; i30<len30; i30++){ -let data373 = data372[i30]; -if(data373 && typeof data373 == "object" && !Array.isArray(data373)){ -if(data373.label === undefined){ -const err703 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30,schemaPath:"#/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err703]; -} -else { -vErrors.push(err703); -} -errors++; -} -for(const key46 in data373){ -if(!(((key46 === "label") || (key46 === "description")) || (key46 === "recommended"))){ -const err704 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30,schemaPath:"#/properties/questions/items/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key46},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err704]; -} -else { -vErrors.push(err704); -} -errors++; -} -} -if(data373.label !== undefined){ -if(typeof data373.label !== "string"){ -const err705 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/label",schemaPath:"#/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err705]; -} -else { -vErrors.push(err705); -} -errors++; -} -} -if(data373.description !== undefined){ -if(typeof data373.description !== "string"){ -const err706 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/description",schemaPath:"#/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err706]; -} -else { -vErrors.push(err706); -} -errors++; -} -} -if(data373.recommended !== undefined){ -if(typeof data373.recommended !== "boolean"){ -const err707 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/recommended",schemaPath:"#/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err707]; -} -else { -vErrors.push(err707); -} -errors++; -} -} -} -else { -const err708 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30,schemaPath:"#/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err708]; -} -else { -vErrors.push(err708); -} -errors++; -} -} -} -} -if(data313.multiple !== undefined){ -if(typeof data313.multiple !== "boolean"){ -const err709 = {instancePath:instancePath+"/questions/" + i26+"/multiple",schemaPath:"#/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err709]; -} -else { -vErrors.push(err709); -} -errors++; -} -} -if(data313.questions !== undefined){ -let data378 = data313.questions; -if((data378 !== null) && (!(Array.isArray(data378)))){ -const err710 = {instancePath:instancePath+"/questions/" + i26+"/questions",schemaPath:"#/properties/questions/items/properties/questions/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err710]; -} -else { -vErrors.push(err710); -} -errors++; -} -if(Array.isArray(data378)){ -const len31 = data378.length; -for(let i31=0; i31<len31; i31++){ -let data379 = data378[i31]; -if(data379 && typeof data379 == "object" && !Array.isArray(data379)){ -if(data379.question === undefined){ -const err711 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31,schemaPath:"#/properties/questions/items/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err711]; -} -else { -vErrors.push(err711); -} -errors++; -} -for(const key47 in data379){ -if(!(((key47 === "question") || (key47 === "options")) || (key47 === "multiple"))){ -const err712 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31,schemaPath:"#/properties/questions/items/properties/questions/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key47},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err712]; -} -else { -vErrors.push(err712); -} -errors++; -} -} -if(data379.question !== undefined){ -if(typeof data379.question !== "string"){ -const err713 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/question",schemaPath:"#/properties/questions/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err713]; -} -else { -vErrors.push(err713); -} -errors++; -} -} -if(data379.options !== undefined){ -let data381 = data379.options; -if((data381 !== null) && (!(Array.isArray(data381)))){ -const err714 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err714]; -} -else { -vErrors.push(err714); -} -errors++; -} -if(Array.isArray(data381)){ -const len32 = data381.length; -for(let i32=0; i32<len32; i32++){ -let data382 = data381[i32]; -if(data382 && typeof data382 == "object" && !Array.isArray(data382)){ -if(data382.label === undefined){ -const err715 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32,schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err715]; -} -else { -vErrors.push(err715); -} -errors++; -} -for(const key48 in data382){ -if(!(((key48 === "label") || (key48 === "description")) || (key48 === "recommended"))){ -const err716 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32,schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key48},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err716]; -} -else { -vErrors.push(err716); -} -errors++; -} -} -if(data382.label !== undefined){ -if(typeof data382.label !== "string"){ -const err717 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/label",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err717]; -} -else { -vErrors.push(err717); -} -errors++; -} -} -if(data382.description !== undefined){ -if(typeof data382.description !== "string"){ -const err718 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/description",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err718]; -} -else { -vErrors.push(err718); -} -errors++; -} -} -if(data382.recommended !== undefined){ -if(typeof data382.recommended !== "boolean"){ -const err719 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/recommended",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err719]; -} -else { -vErrors.push(err719); -} -errors++; -} -} -} -else { -const err720 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32,schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err720]; -} -else { -vErrors.push(err720); -} -errors++; -} -} -} -} -if(data379.multiple !== undefined){ -if(typeof data379.multiple !== "boolean"){ -const err721 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/multiple",schemaPath:"#/properties/questions/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err721]; -} -else { -vErrors.push(err721); -} -errors++; -} -} -} -else { -const err722 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31,schemaPath:"#/properties/questions/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err722]; -} -else { -vErrors.push(err722); -} -errors++; -} -} -} -} -if(data313.answer !== undefined){ -let data387 = data313.answer; -if((data387 !== null) && (!(Array.isArray(data387)))){ -const err723 = {instancePath:instancePath+"/questions/" + i26+"/answer",schemaPath:"#/properties/questions/items/properties/answer/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err723]; -} -else { -vErrors.push(err723); -} -errors++; -} -if(Array.isArray(data387)){ -const len33 = data387.length; -for(let i33=0; i33<len33; i33++){ -if(typeof data387[i33] !== "string"){ -const err724 = {instancePath:instancePath+"/questions/" + i26+"/answer/" + i33,schemaPath:"#/properties/questions/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err724]; -} -else { -vErrors.push(err724); -} -errors++; -} -} -} -} -if(data313.dismissed !== undefined){ -if(typeof data313.dismissed !== "boolean"){ -const err725 = {instancePath:instancePath+"/questions/" + i26+"/dismissed",schemaPath:"#/properties/questions/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err725]; -} -else { -vErrors.push(err725); -} -errors++; -} -} -if(data313.answers !== undefined){ -let data390 = data313.answers; -if((data390 !== null) && (!(Array.isArray(data390)))){ -const err726 = {instancePath:instancePath+"/questions/" + i26+"/answers",schemaPath:"#/properties/questions/items/properties/answers/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err726]; -} -else { -vErrors.push(err726); -} -errors++; -} -if(Array.isArray(data390)){ -const len34 = data390.length; -for(let i34=0; i34<len34; i34++){ -let data391 = data390[i34]; -if(data391 && typeof data391 == "object" && !Array.isArray(data391)){ -for(const key49 in data391){ -if(!((key49 === "answer") || (key49 === "dismissed"))){ -const err727 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34,schemaPath:"#/properties/questions/items/properties/answers/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key49},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err727]; -} -else { -vErrors.push(err727); -} -errors++; -} -} -if(data391.answer !== undefined){ -let data392 = data391.answer; -if((data392 !== null) && (!(Array.isArray(data392)))){ -const err728 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/answer",schemaPath:"#/properties/questions/items/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err728]; -} -else { -vErrors.push(err728); -} -errors++; -} -if(Array.isArray(data392)){ -const len35 = data392.length; -for(let i35=0; i35<len35; i35++){ -if(typeof data392[i35] !== "string"){ -const err729 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/answer/" + i35,schemaPath:"#/properties/questions/items/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err729]; -} -else { -vErrors.push(err729); -} -errors++; -} -} -} -} -if(data391.dismissed !== undefined){ -if(typeof data391.dismissed !== "boolean"){ -const err730 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/dismissed",schemaPath:"#/properties/questions/items/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err730]; -} -else { -vErrors.push(err730); -} -errors++; -} -} -} -else { -const err731 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34,schemaPath:"#/properties/questions/items/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err731]; -} -else { -vErrors.push(err731); -} -errors++; -} -} -} -} -} -else { -const err732 = {instancePath:instancePath+"/questions/" + i26,schemaPath:"#/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err732]; -} -else { -vErrors.push(err732); -} -errors++; -} -} -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err733 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err733]; -} -else { -vErrors.push(err733); -} -errors++; -} -} -} -else { -const err734 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err734]; -} -else { -vErrors.push(err734); -} -errors++; -} -validate159.errors = vErrors; -return errors === 0; -} - -export const RunConfigureParams = validate160; -const schema161 = {"type":"object","properties":{"system":{"type":"string"},"max_turns":{"type":"integer"},"headless":{"type":"boolean"},"cache_key":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RunConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RunConfigureParams","additionalProperties":false}; - -function validate160(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RunConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((((key0 === "system") || (key0 === "max_turns")) || (key0 === "headless")) || (key0 === "cache_key"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.system !== undefined){ -if(typeof data.system !== "string"){ -const err1 = {instancePath:instancePath+"/system",schemaPath:"#/properties/system/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.max_turns !== undefined){ -let data1 = data.max_turns; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err2 = {instancePath:instancePath+"/max_turns",schemaPath:"#/properties/max_turns/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.headless !== undefined){ -if(typeof data.headless !== "boolean"){ -const err3 = {instancePath:instancePath+"/headless",schemaPath:"#/properties/headless/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cache_key !== undefined){ -if(typeof data.cache_key !== "string"){ -const err4 = {instancePath:instancePath+"/cache_key",schemaPath:"#/properties/cache_key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate160.errors = vErrors; -return errors === 0; -} - -export const RuntimeConfiguration = validate161; -const schema162 = {"type":"object","properties":{"default_execution_engine":{"type":"string"},"disabled_providers":{"type":["null","array"],"items":{"type":"string"}},"discovery":{"type":["null","object"],"properties":{"status":{"type":"string"},"message":{"type":"string"},"model_count":{"type":"integer"}},"required":["status"],"additionalProperties":false},"remote_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"runtime_id":{"type":"string"},"connect_on_launch":{"type":"boolean"}},"required":["id","name","url","runtime_id","connect_on_launch"],"additionalProperties":false}},"import_claude":{"type":"boolean"},"import_codex":{"type":"boolean"},"mcp_import_offered":{"type":"boolean"},"brand_icons":{"type":"boolean"},"revision":{"type":"string"},"default_model":{"type":"string"},"default_provider":{"type":"string"},"default_effort":{"type":"string"},"default_permission_mode":{"type":"string"},"compact_model":{"type":"string"},"compact_provider":{"type":"string"},"compact_percent":{"type":"integer"},"goal_max_rounds":{"type":"integer"},"max_retries":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RuntimeConfiguration","$schema":"http://json-schema.org/draft-07/schema#","title":"RuntimeConfiguration","required":["default_execution_engine","import_claude","import_codex","mcp_import_offered","brand_icons","revision","default_model","default_provider","default_effort","compact_model","compact_provider","compact_percent","goal_max_rounds","max_retries"],"additionalProperties":false}; - -function validate161(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RuntimeConfiguration" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.default_execution_engine === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_execution_engine"},message:"must have required property '"+"default_execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.import_claude === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "import_claude"},message:"must have required property '"+"import_claude"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.import_codex === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "import_codex"},message:"must have required property '"+"import_codex"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.mcp_import_offered === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp_import_offered"},message:"must have required property '"+"mcp_import_offered"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.brand_icons === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "brand_icons"},message:"must have required property '"+"brand_icons"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.revision === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.default_model === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_model"},message:"must have required property '"+"default_model"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.default_provider === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_provider"},message:"must have required property '"+"default_provider"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.default_effort === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_effort"},message:"must have required property '"+"default_effort"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.compact_model === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_model"},message:"must have required property '"+"compact_model"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.compact_provider === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_provider"},message:"must have required property '"+"compact_provider"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.compact_percent === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_percent"},message:"must have required property '"+"compact_percent"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.goal_max_rounds === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "goal_max_rounds"},message:"must have required property '"+"goal_max_rounds"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.max_retries === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_retries"},message:"must have required property '"+"max_retries"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema162.properties, key0))){ -const err14 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.default_execution_engine !== undefined){ -if(typeof data.default_execution_engine !== "string"){ -const err15 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.disabled_providers !== undefined){ -let data1 = data.disabled_providers; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err16 = {instancePath:instancePath+"/disabled_providers",schemaPath:"#/properties/disabled_providers/type",keyword:"type",params:{type: schema162.properties.disabled_providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err17 = {instancePath:instancePath+"/disabled_providers/" + i0,schemaPath:"#/properties/disabled_providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.discovery !== undefined){ -let data3 = data.discovery; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err18 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/type",keyword:"type",params:{type: schema162.properties.discovery.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.status === undefined){ -const err19 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -for(const key1 in data3){ -if(!(((key1 === "status") || (key1 === "message")) || (key1 === "model_count"))){ -const err20 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data3.status !== undefined){ -if(typeof data3.status !== "string"){ -const err21 = {instancePath:instancePath+"/discovery/status",schemaPath:"#/properties/discovery/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data3.message !== undefined){ -if(typeof data3.message !== "string"){ -const err22 = {instancePath:instancePath+"/discovery/message",schemaPath:"#/properties/discovery/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data3.model_count !== undefined){ -let data6 = data3.model_count; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err23 = {instancePath:instancePath+"/discovery/model_count",schemaPath:"#/properties/discovery/properties/model_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data.remote_hosts !== undefined){ -let data7 = data.remote_hosts; -if((data7 !== null) && (!(Array.isArray(data7)))){ -const err24 = {instancePath:instancePath+"/remote_hosts",schemaPath:"#/properties/remote_hosts/type",keyword:"type",params:{type: schema162.properties.remote_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data7)){ -const len1 = data7.length; -for(let i1=0; i1<len1; i1++){ -let data8 = data7[i1]; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.id === undefined){ -const err25 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data8.name === undefined){ -const err26 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data8.url === undefined){ -const err27 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data8.runtime_id === undefined){ -const err28 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data8.connect_on_launch === undefined){ -const err29 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "connect_on_launch"},message:"must have required property '"+"connect_on_launch"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -for(const key2 in data8){ -if(!(((((key2 === "id") || (key2 === "name")) || (key2 === "url")) || (key2 === "runtime_id")) || (key2 === "connect_on_launch"))){ -const err30 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data8.id !== undefined){ -if(typeof data8.id !== "string"){ -const err31 = {instancePath:instancePath+"/remote_hosts/" + i1+"/id",schemaPath:"#/properties/remote_hosts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data8.name !== undefined){ -if(typeof data8.name !== "string"){ -const err32 = {instancePath:instancePath+"/remote_hosts/" + i1+"/name",schemaPath:"#/properties/remote_hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data8.url !== undefined){ -if(typeof data8.url !== "string"){ -const err33 = {instancePath:instancePath+"/remote_hosts/" + i1+"/url",schemaPath:"#/properties/remote_hosts/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data8.runtime_id !== undefined){ -if(typeof data8.runtime_id !== "string"){ -const err34 = {instancePath:instancePath+"/remote_hosts/" + i1+"/runtime_id",schemaPath:"#/properties/remote_hosts/items/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data8.connect_on_launch !== undefined){ -if(typeof data8.connect_on_launch !== "boolean"){ -const err35 = {instancePath:instancePath+"/remote_hosts/" + i1+"/connect_on_launch",schemaPath:"#/properties/remote_hosts/items/properties/connect_on_launch/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -else { -const err36 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -} -if(data.import_claude !== undefined){ -if(typeof data.import_claude !== "boolean"){ -const err37 = {instancePath:instancePath+"/import_claude",schemaPath:"#/properties/import_claude/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data.import_codex !== undefined){ -if(typeof data.import_codex !== "boolean"){ -const err38 = {instancePath:instancePath+"/import_codex",schemaPath:"#/properties/import_codex/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data.mcp_import_offered !== undefined){ -if(typeof data.mcp_import_offered !== "boolean"){ -const err39 = {instancePath:instancePath+"/mcp_import_offered",schemaPath:"#/properties/mcp_import_offered/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data.brand_icons !== undefined){ -if(typeof data.brand_icons !== "boolean"){ -const err40 = {instancePath:instancePath+"/brand_icons",schemaPath:"#/properties/brand_icons/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err41 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data.default_model !== undefined){ -if(typeof data.default_model !== "string"){ -const err42 = {instancePath:instancePath+"/default_model",schemaPath:"#/properties/default_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data.default_provider !== undefined){ -if(typeof data.default_provider !== "string"){ -const err43 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data.default_effort !== undefined){ -if(typeof data.default_effort !== "string"){ -const err44 = {instancePath:instancePath+"/default_effort",schemaPath:"#/properties/default_effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.default_permission_mode !== undefined){ -if(typeof data.default_permission_mode !== "string"){ -const err45 = {instancePath:instancePath+"/default_permission_mode",schemaPath:"#/properties/default_permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data.compact_model !== undefined){ -if(typeof data.compact_model !== "string"){ -const err46 = {instancePath:instancePath+"/compact_model",schemaPath:"#/properties/compact_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data.compact_provider !== undefined){ -if(typeof data.compact_provider !== "string"){ -const err47 = {instancePath:instancePath+"/compact_provider",schemaPath:"#/properties/compact_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data.compact_percent !== undefined){ -let data25 = data.compact_percent; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err48 = {instancePath:instancePath+"/compact_percent",schemaPath:"#/properties/compact_percent/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data.goal_max_rounds !== undefined){ -let data26 = data.goal_max_rounds; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err49 = {instancePath:instancePath+"/goal_max_rounds",schemaPath:"#/properties/goal_max_rounds/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data.max_retries !== undefined){ -let data27 = data.max_retries; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err50 = {instancePath:instancePath+"/max_retries",schemaPath:"#/properties/max_retries/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -else { -const err51 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -validate161.errors = vErrors; -return errors === 0; -} - -export const ScheduleCreateParams = validate162; -const schema163 = {"type":"object","properties":{"schedule":{"type":"string"},"prompt":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ScheduleCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleCreateParams","required":["schedule","prompt"],"additionalProperties":false}; - -function validate162(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.prompt === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "schedule") || (key0 === "prompt"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.schedule !== undefined){ -if(typeof data.schedule !== "string"){ -const err3 = {instancePath:instancePath+"/schedule",schemaPath:"#/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.prompt !== undefined){ -if(typeof data.prompt !== "string"){ -const err4 = {instancePath:instancePath+"/prompt",schemaPath:"#/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate162.errors = vErrors; -return errors === 0; -} - -export const ScheduleDeleteParams = validate163; -const schema164 = {"type":"object","properties":{"schedule_id":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ScheduleDeleteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleDeleteParams","required":["schedule_id"],"additionalProperties":false}; - -function validate163(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleDeleteParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule_id"},message:"must have required property '"+"schedule_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "schedule_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.schedule_id !== undefined){ -let data0 = data.schedule_id; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err2 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate163.errors = vErrors; -return errors === 0; -} - -export const ScheduleListResult = validate164; -const schema165 = {"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/ScheduleListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleListResult"}; - -function validate164(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema165.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.schedule === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.prompt === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.anchor === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.last_fire === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key0 in data0){ -if(!(((((key0 === "id") || (key0 === "schedule")) || (key0 === "prompt")) || (key0 === "anchor")) || (key0 === "last_fire"))){ -const err6 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.id !== undefined){ -let data1 = data0.id; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err7 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.schedule !== undefined){ -if(typeof data0.schedule !== "string"){ -const err8 = {instancePath:instancePath+"/" + i0+"/schedule",schemaPath:"#/items/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.prompt !== undefined){ -if(typeof data0.prompt !== "string"){ -const err9 = {instancePath:instancePath+"/" + i0+"/prompt",schemaPath:"#/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.anchor !== undefined){ -if(typeof data0.anchor !== "string"){ -const err10 = {instancePath:instancePath+"/" + i0+"/anchor",schemaPath:"#/items/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.last_fire !== undefined){ -if(typeof data0.last_fire !== "string"){ -const err11 = {instancePath:instancePath+"/" + i0+"/last_fire",schemaPath:"#/items/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -validate164.errors = vErrors; -return errors === 0; -} - -export const ScheduleResult = validate165; -const schema166 = {"type":"object","properties":{"schedule_id":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ScheduleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleResult","required":["schedule_id"],"additionalProperties":false}; - -function validate165(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule_id"},message:"must have required property '"+"schedule_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "schedule_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.schedule_id !== undefined){ -let data0 = data.schedule_id; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err2 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate165.errors = vErrors; -return errors === 0; -} - -export const SessionCatalogPage = validate166; -const schema167 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"workspace_id":{"type":"string"},"pinned":{"type":"boolean"},"archived":{"type":"boolean"},"updated_at":{"type":"string"},"truncated":{"type":"boolean"}},"required":["id","kind","title","model","provider","cwd","pinned","archived","updated_at","truncated"],"additionalProperties":false}},"next_cursor":{"type":["null","object"],"properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]}},"required":["revision","offset","status"],"additionalProperties":false},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/SessionCatalogPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionCatalogPage","required":["revision","items","has_more"],"additionalProperties":false}; - -function validate166(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionCatalogPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.has_more === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "revision") || (key0 === "items")) || (key0 === "next_cursor")) || (key0 === "has_more"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.items !== undefined){ -let data1 = data.items; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err7 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema167.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.kind === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.title === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.model === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.provider === undefined){ -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.cwd === undefined){ -const err13 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.pinned === undefined){ -const err14 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.archived === undefined){ -const err15 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.updated_at === undefined){ -const err16 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.truncated === undefined){ -const err17 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key1 in data2){ -if(!(func2.call(schema167.properties.items.items.properties, key1))){ -const err18 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/kind",schemaPath:"#/properties/items/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data2.title !== undefined){ -if(typeof data2.title !== "string"){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.model !== undefined){ -if(typeof data2.model !== "string"){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/model",schemaPath:"#/properties/items/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.provider !== undefined){ -if(typeof data2.provider !== "string"){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/provider",schemaPath:"#/properties/items/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.cwd !== undefined){ -if(typeof data2.cwd !== "string"){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/cwd",schemaPath:"#/properties/items/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.workspace_id !== undefined){ -if(typeof data2.workspace_id !== "string"){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/workspace_id",schemaPath:"#/properties/items/items/properties/workspace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.pinned !== undefined){ -if(typeof data2.pinned !== "boolean"){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/pinned",schemaPath:"#/properties/items/items/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.archived !== undefined){ -if(typeof data2.archived !== "boolean"){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/archived",schemaPath:"#/properties/items/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.updated_at !== undefined){ -if(typeof data2.updated_at !== "string"){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/updated_at",schemaPath:"#/properties/items/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data2.truncated !== undefined){ -if(typeof data2.truncated !== "boolean"){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -else { -const err30 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -} -if(data.next_cursor !== undefined){ -let data14 = data.next_cursor; -if((data14 !== null) && (!(data14 && typeof data14 == "object" && !Array.isArray(data14)))){ -const err31 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema167.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.revision === undefined){ -const err32 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data14.offset === undefined){ -const err33 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data14.status === undefined){ -const err34 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -for(const key2 in data14){ -if(!((((key2 === "revision") || (key2 === "offset")) || (key2 === "search")) || (key2 === "status"))){ -const err35 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data14.revision !== undefined){ -let data15 = data14.revision; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err36 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err37 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -else { -const err38 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data14.offset !== undefined){ -let data16 = data14.offset; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err39 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err40 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -else { -const err41 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data14.search !== undefined){ -if(typeof data14.search !== "string"){ -const err42 = {instancePath:instancePath+"/next_cursor/search",schemaPath:"#/properties/next_cursor/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data14.status !== undefined){ -let data18 = data14.status; -if(typeof data18 !== "string"){ -const err43 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(((data18 === "active") || (data18 === "archived")) || (data18 === "all"))){ -const err44 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/enum",keyword:"enum",params:{allowedValues: schema167.properties.next_cursor.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err45 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -else { -const err46 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -validate166.errors = vErrors; -return errors === 0; -} - -export const SessionCatalogParams = validate167; -const schema168 = {"type":"object","properties":{"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]},"cursor":{"type":["null","object"],"properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]}},"required":["revision","offset","status"],"additionalProperties":false},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/SessionCatalogParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionCatalogParams","required":["limit","max_bytes"],"additionalProperties":false}; - -function validate167(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionCatalogParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.max_bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "search") || (key0 === "status")) || (key0 === "cursor")) || (key0 === "limit")) || (key0 === "max_bytes"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.search !== undefined){ -if(typeof data.search !== "string"){ -const err3 = {instancePath:instancePath+"/search",schemaPath:"#/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.status !== undefined){ -let data1 = data.status; -if(typeof data1 !== "string"){ -const err4 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(((data1 === "active") || (data1 === "archived")) || (data1 === "all"))){ -const err5 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/enum",keyword:"enum",params:{allowedValues: schema168.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema168.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.revision === undefined){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.offset === undefined){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.status === undefined){ -const err9 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key1 in data2){ -if(!((((key1 === "revision") || (key1 === "offset")) || (key1 === "search")) || (key1 === "status"))){ -const err10 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data2.revision !== undefined){ -let data3 = data2.revision; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err11 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err12 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -else { -const err13 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data2.offset !== undefined){ -let data4 = data2.offset; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err14 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err15 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -else { -const err16 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data2.search !== undefined){ -if(typeof data2.search !== "string"){ -const err17 = {instancePath:instancePath+"/cursor/search",schemaPath:"#/properties/cursor/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data2.status !== undefined){ -let data6 = data2.status; -if(typeof data6 !== "string"){ -const err18 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(((data6 === "active") || (data6 === "archived")) || (data6 === "all"))){ -const err19 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/enum",keyword:"enum",params:{allowedValues: schema168.properties.cursor.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data7 = data.limit; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err20 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data8 = data.max_bytes; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err21 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -else { -const err22 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -validate167.errors = vErrors; -return errors === 0; -} - -export const SessionListResult = validate168; -const schema169 = {"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"definition_revision":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"goal":{"type":"string"},"forked_from":{"type":"string"},"fork_seq":{"type":"integer"},"tags":{"type":["null","array"],"items":{"type":"string"}},"archived":{"type":"boolean"},"pinned":{"type":"boolean"},"effort":{"type":"string"},"usage_in":{"type":"integer"},"usage_cached":{"type":"integer"},"usage_out":{"type":"integer"},"updated_at":{"type":"string"}},"required":["execution_engine","definition","definition_revision","id","kind","title","model","provider","cwd","goal","forked_from","fork_seq","tags","archived","pinned","effort","usage_in","usage_cached","usage_out","updated_at"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/SessionListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionListResult"}; - -function validate168(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema169.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.execution_engine === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.definition === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.definition_revision === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "definition_revision"},message:"must have required property '"+"definition_revision"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.id === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.kind === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.title === undefined){ -const err6 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.model === undefined){ -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.provider === undefined){ -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.cwd === undefined){ -const err9 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.goal === undefined){ -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.forked_from === undefined){ -const err11 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "forked_from"},message:"must have required property '"+"forked_from"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.fork_seq === undefined){ -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "fork_seq"},message:"must have required property '"+"fork_seq"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.tags === undefined){ -const err13 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "tags"},message:"must have required property '"+"tags"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.archived === undefined){ -const err14 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.pinned === undefined){ -const err15 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.effort === undefined){ -const err16 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data0.usage_in === undefined){ -const err17 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_in"},message:"must have required property '"+"usage_in"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data0.usage_cached === undefined){ -const err18 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_cached"},message:"must have required property '"+"usage_cached"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data0.usage_out === undefined){ -const err19 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_out"},message:"must have required property '"+"usage_out"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data0.updated_at === undefined){ -const err20 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key0 in data0){ -if(!(func2.call(schema169.items.properties, key0))){ -const err21 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data0.execution_engine !== undefined){ -if(typeof data0.execution_engine !== "string"){ -const err22 = {instancePath:instancePath+"/" + i0+"/execution_engine",schemaPath:"#/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data0.definition !== undefined){ -if(typeof data0.definition !== "string"){ -const err23 = {instancePath:instancePath+"/" + i0+"/definition",schemaPath:"#/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data0.definition_revision !== undefined){ -if(typeof data0.definition_revision !== "string"){ -const err24 = {instancePath:instancePath+"/" + i0+"/definition_revision",schemaPath:"#/items/properties/definition_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err25 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err26 = {instancePath:instancePath+"/" + i0+"/kind",schemaPath:"#/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data0.title !== undefined){ -if(typeof data0.title !== "string"){ -const err27 = {instancePath:instancePath+"/" + i0+"/title",schemaPath:"#/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data0.model !== undefined){ -if(typeof data0.model !== "string"){ -const err28 = {instancePath:instancePath+"/" + i0+"/model",schemaPath:"#/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data0.provider !== undefined){ -if(typeof data0.provider !== "string"){ -const err29 = {instancePath:instancePath+"/" + i0+"/provider",schemaPath:"#/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data0.cwd !== undefined){ -if(typeof data0.cwd !== "string"){ -const err30 = {instancePath:instancePath+"/" + i0+"/cwd",schemaPath:"#/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data0.goal !== undefined){ -if(typeof data0.goal !== "string"){ -const err31 = {instancePath:instancePath+"/" + i0+"/goal",schemaPath:"#/items/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data0.forked_from !== undefined){ -if(typeof data0.forked_from !== "string"){ -const err32 = {instancePath:instancePath+"/" + i0+"/forked_from",schemaPath:"#/items/properties/forked_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data0.fork_seq !== undefined){ -let data12 = data0.fork_seq; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err33 = {instancePath:instancePath+"/" + i0+"/fork_seq",schemaPath:"#/items/properties/fork_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data0.tags !== undefined){ -let data13 = data0.tags; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err34 = {instancePath:instancePath+"/" + i0+"/tags",schemaPath:"#/items/properties/tags/type",keyword:"type",params:{type: schema169.items.properties.tags.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(Array.isArray(data13)){ -const len1 = data13.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data13[i1] !== "string"){ -const err35 = {instancePath:instancePath+"/" + i0+"/tags/" + i1,schemaPath:"#/items/properties/tags/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -} -if(data0.archived !== undefined){ -if(typeof data0.archived !== "boolean"){ -const err36 = {instancePath:instancePath+"/" + i0+"/archived",schemaPath:"#/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data0.pinned !== undefined){ -if(typeof data0.pinned !== "boolean"){ -const err37 = {instancePath:instancePath+"/" + i0+"/pinned",schemaPath:"#/items/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data0.effort !== undefined){ -if(typeof data0.effort !== "string"){ -const err38 = {instancePath:instancePath+"/" + i0+"/effort",schemaPath:"#/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data0.usage_in !== undefined){ -let data18 = data0.usage_in; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err39 = {instancePath:instancePath+"/" + i0+"/usage_in",schemaPath:"#/items/properties/usage_in/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data0.usage_cached !== undefined){ -let data19 = data0.usage_cached; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err40 = {instancePath:instancePath+"/" + i0+"/usage_cached",schemaPath:"#/items/properties/usage_cached/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data0.usage_out !== undefined){ -let data20 = data0.usage_out; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err41 = {instancePath:instancePath+"/" + i0+"/usage_out",schemaPath:"#/items/properties/usage_out/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data0.updated_at !== undefined){ -if(typeof data0.updated_at !== "string"){ -const err42 = {instancePath:instancePath+"/" + i0+"/updated_at",schemaPath:"#/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -else { -const err43 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -validate168.errors = vErrors; -return errors === 0; -} - -export const SessionMetadata = validate169; -const schema170 = {"type":"object","properties":{"root_id":{"type":"string"},"title":{"type":"string"},"cwd":{"type":"string"},"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/SessionMetadata","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionMetadata","required":["root_id","title","cwd","history_revision","archived"],"additionalProperties":false}; - -function validate169(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionMetadata" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.title === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cwd === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.history_revision === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.archived === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "title")) || (key0 === "cwd")) || (key0 === "history_revision")) || (key0 === "archived"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err7 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err8 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.history_revision !== undefined){ -let data3 = data.history_revision; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err9 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err10 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err12 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate169.errors = vErrors; -return errors === 0; -} - -export const SessionPreviewResult = validate170; -const schema171 = {"type":"object","properties":{"root_id":{"type":"string"},"user":{"type":"string"},"assistant":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionPreviewResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionPreviewResult","required":["root_id","user","assistant"],"additionalProperties":false}; - -function validate170(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionPreviewResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.user === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "user"},message:"must have required property '"+"user"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.assistant === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "assistant"},message:"must have required property '"+"assistant"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "root_id") || (key0 === "user")) || (key0 === "assistant"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.user !== undefined){ -if(typeof data.user !== "string"){ -const err5 = {instancePath:instancePath+"/user",schemaPath:"#/properties/user/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.assistant !== undefined){ -if(typeof data.assistant !== "string"){ -const err6 = {instancePath:instancePath+"/assistant",schemaPath:"#/properties/assistant/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate170.errors = vErrors; -return errors === 0; -} - -export const SessionSummariesParams = validate171; -const schema172 = {"type":"object","properties":{"root_ids":{"type":"array","items":{"type":"string","pattern":"^[\\s\\S]{1,256}$"},"maxItems":32,"uniqueItems":true}},"$id":"https://whip.dev/protocol/v6/SessionSummariesParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionSummariesParams","required":["root_ids"],"additionalProperties":false}; -const pattern205 = new RegExp("^[\\s\\S]{1,256}$", "u"); - -function validate171(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionSummariesParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_ids === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_ids"},message:"must have required property '"+"root_ids"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "root_ids")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_ids !== undefined){ -let data0 = data.root_ids; -if(Array.isArray(data0)){ -if(data0.length > 32){ -const err2 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/maxItems",keyword:"maxItems",params:{limit: 32},message:"must NOT have more than 32 items"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(typeof data1 === "string"){ -if(!pattern205.test(data1)){ -const err3 = {instancePath:instancePath+"/root_ids/" + i0,schemaPath:"#/properties/root_ids/items/pattern",keyword:"pattern",params:{pattern: "^[\\s\\S]{1,256}$"},message:"must match pattern \""+"^[\\s\\S]{1,256}$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/root_ids/" + i0,schemaPath:"#/properties/root_ids/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -let i1 = data0.length; -let j0; -if(i1 > 1){ -const indices0 = {}; -for(;i1--;){ -let item0 = data0[i1]; -if(typeof item0 !== "string"){ -continue; -} -if(typeof indices0[item0] == "number"){ -j0 = indices0[item0]; -const err5 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -break; -} -indices0[item0] = i1; -} -} -} -else { -const err6 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate171.errors = vErrors; -return errors === 0; -} - -export const SessionSummariesResult = validate172; -const schema173 = {"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"root_id":{"type":"string"},"missing":{"type":"boolean"},"archived":{"type":"boolean"},"title":{"type":"string"},"cwd":{"type":"string"},"workspace_id":{"type":"string"},"running_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"queued_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_permissions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_questions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"truncated":{"type":"boolean"}},"required":["root_id","missing","archived","title","cwd","running_agents","queued_agents","pending_permissions","pending_questions","truncated"],"additionalProperties":false},"maxItems":32}},"$id":"https://whip.dev/protocol/v6/SessionSummariesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionSummariesResult","required":["items"],"additionalProperties":false}; - -function validate172(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionSummariesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "items")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.items !== undefined){ -let data0 = data.items; -if(Array.isArray(data0)){ -if(data0.length > 32){ -const err2 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/maxItems",keyword:"maxItems",params:{limit: 32},message:"must NOT have more than 32 items"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err3 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.missing === undefined){ -const err4 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "missing"},message:"must have required property '"+"missing"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.archived === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.title === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.cwd === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.running_agents === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "running_agents"},message:"must have required property '"+"running_agents"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.queued_agents === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "queued_agents"},message:"must have required property '"+"queued_agents"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.pending_permissions === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_permissions"},message:"must have required property '"+"pending_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data1.pending_questions === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_questions"},message:"must have required property '"+"pending_questions"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data1.truncated === undefined){ -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -for(const key1 in data1){ -if(!(func2.call(schema173.properties.items.items.properties, key1))){ -const err13 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err14 = {instancePath:instancePath+"/items/" + i0+"/root_id",schemaPath:"#/properties/items/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.missing !== undefined){ -if(typeof data1.missing !== "boolean"){ -const err15 = {instancePath:instancePath+"/items/" + i0+"/missing",schemaPath:"#/properties/items/items/properties/missing/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data1.archived !== undefined){ -if(typeof data1.archived !== "boolean"){ -const err16 = {instancePath:instancePath+"/items/" + i0+"/archived",schemaPath:"#/properties/items/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data1.title !== undefined){ -if(typeof data1.title !== "string"){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data1.cwd !== undefined){ -if(typeof data1.cwd !== "string"){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/cwd",schemaPath:"#/properties/items/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data1.workspace_id !== undefined){ -if(typeof data1.workspace_id !== "string"){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/workspace_id",schemaPath:"#/properties/items/items/properties/workspace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.running_agents !== undefined){ -let data8 = data1.running_agents; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -else { -const err22 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data1.queued_agents !== undefined){ -let data9 = data1.queued_agents; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data1.pending_permissions !== undefined){ -let data10 = data1.pending_permissions; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data1.pending_questions !== undefined){ -let data11 = data1.pending_questions; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data1.truncated !== undefined){ -if(typeof data1.truncated !== "boolean"){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -else { -const err34 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -else { -const err35 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -validate172.errors = vErrors; -return errors === 0; -} - -export const SessionTitleChangedParams = validate173; -const schema174 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionTitleChangedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionTitleChangedParams","required":["root_id"],"additionalProperties":false}; - -function validate173(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionTitleChangedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "root_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate173.errors = vErrors; -return errors === 0; -} - -export const SessionUpdateEvent = validate174; -const schema175 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":false}; - -function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionUpdateEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!((((((((key0 === "archived") || (key0 === "title")) || (key0 === "model")) || (key0 === "provider")) || (key0 === "effort")) || (key0 === "effort_changed")) || (key0 === "working_directory")) || (key0 === "permission_mode"))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.archived !== undefined){ -let data0 = data.archived; -if((data0 !== null) && (typeof data0 !== "boolean")){ -const err1 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema175.properties.archived.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err2 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err3 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err5 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.effort_changed !== undefined){ -if(typeof data.effort_changed !== "boolean"){ -const err6 = {instancePath:instancePath+"/effort_changed",schemaPath:"#/properties/effort_changed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.working_directory !== undefined){ -if(typeof data.working_directory !== "string"){ -const err7 = {instancePath:instancePath+"/working_directory",schemaPath:"#/properties/working_directory/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -let data7 = data.permission_mode; -if((data7 !== null) && (typeof data7 !== "string")){ -const err8 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema175.properties.permission_mode.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate174.errors = vErrors; -return errors === 0; -} - -export const ShellParams = validate175; -const schema176 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":false}; - -function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ShellParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "command")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.command !== undefined){ -if(typeof data.command !== "string"){ -const err2 = {instancePath:instancePath+"/command",schemaPath:"#/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate175.errors = vErrors; -return errors === 0; -} - -export const SnapshotParams = validate176; -const schema177 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":false}; - -function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SnapshotParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "root_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate176.errors = vErrors; -return errors === 0; -} - -export const SpanPage = validate177; -const schema178 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":false}; - -function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SpanPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.spans === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "spans"},message:"must have required property '"+"spans"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.next_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.server_time_ns === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "server_time_ns"},message:"must have required property '"+"server_time_ns"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "spans")) || (key0 === "next_seq")) || (key0 === "has_more")) || (key0 === "server_time_ns"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.spans !== undefined){ -let data1 = data.spans; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err7 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema178.properties.spans.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err8 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.trace_id === undefined){ -const err9 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "trace_id"},message:"must have required property '"+"trace_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.root_id === undefined){ -const err10 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.agent_id === undefined){ -const err11 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.kind === undefined){ -const err12 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.name === undefined){ -const err13 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.status === undefined){ -const err14 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.start_ns === undefined){ -const err15 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "start_ns"},message:"must have required property '"+"start_ns"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.end_ns === undefined){ -const err16 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "end_ns"},message:"must have required property '"+"end_ns"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.updated_seq === undefined){ -const err17 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "updated_seq"},message:"must have required property '"+"updated_seq"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -for(const key1 in data2){ -if(!(func2.call(schema178.properties.spans.items.properties, key1))){ -const err18 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err19 = {instancePath:instancePath+"/spans/" + i0+"/id",schemaPath:"#/properties/spans/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data2.trace_id !== undefined){ -if(typeof data2.trace_id !== "string"){ -const err20 = {instancePath:instancePath+"/spans/" + i0+"/trace_id",schemaPath:"#/properties/spans/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data2.parent_id !== undefined){ -if(typeof data2.parent_id !== "string"){ -const err21 = {instancePath:instancePath+"/spans/" + i0+"/parent_id",schemaPath:"#/properties/spans/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.root_id !== undefined){ -if(typeof data2.root_id !== "string"){ -const err22 = {instancePath:instancePath+"/spans/" + i0+"/root_id",schemaPath:"#/properties/spans/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.agent_id !== undefined){ -if(typeof data2.agent_id !== "string"){ -const err23 = {instancePath:instancePath+"/spans/" + i0+"/agent_id",schemaPath:"#/properties/spans/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.turn_id !== undefined){ -if(typeof data2.turn_id !== "string"){ -const err24 = {instancePath:instancePath+"/spans/" + i0+"/turn_id",schemaPath:"#/properties/spans/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err25 = {instancePath:instancePath+"/spans/" + i0+"/kind",schemaPath:"#/properties/spans/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err26 = {instancePath:instancePath+"/spans/" + i0+"/name",schemaPath:"#/properties/spans/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err27 = {instancePath:instancePath+"/spans/" + i0+"/status",schemaPath:"#/properties/spans/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.start_ns !== undefined){ -let data12 = data2.start_ns; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err28 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err29 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -else { -const err30 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data2.end_ns !== undefined){ -let data13 = data2.end_ns; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err31 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err32 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -else { -const err33 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data2.updated_seq !== undefined){ -let data14 = data2.updated_seq; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err34 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err35 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -else { -const err36 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -else { -const err37 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -} -} -if(data.next_seq !== undefined){ -let data15 = data.next_seq; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err38 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err39 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -else { -const err40 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err41 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data.server_time_ns !== undefined){ -let data17 = data.server_time_ns; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err42 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err43 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -else { -const err44 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -else { -const err45 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -validate177.errors = vErrors; -return errors === 0; -} - -export const SpanRecord = validate178; -const schema179 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":false}; - -function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SpanRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.trace_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "trace_id"},message:"must have required property '"+"trace_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.kind === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.name === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.status === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.start_ns === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "start_ns"},message:"must have required property '"+"start_ns"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.end_ns === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "end_ns"},message:"must have required property '"+"end_ns"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.updated_seq === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "updated_seq"},message:"must have required property '"+"updated_seq"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema179.properties, key0))){ -const err10 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err11 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err12 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.parent_id !== undefined){ -if(typeof data.parent_id !== "string"){ -const err13 = {instancePath:instancePath+"/parent_id",schemaPath:"#/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err14 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err15 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err16 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err17 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err18 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err19 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.start_ns !== undefined){ -let data9 = data.start_ns; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err20 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err21 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -else { -const err22 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.end_ns !== undefined){ -let data10 = data.end_ns; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err23 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err24 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data.updated_seq !== undefined){ -let data11 = data.updated_seq; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err26 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err27 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -validate178.errors = vErrors; -return errors === 0; -} - -export const StreamEvent = validate179; -const schema180 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":false},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":false},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":false},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":false}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":false}},"required":["used","size","usage"],"additionalProperties":false},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":false}; - -function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/StreamEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -for(const key0 in data){ -if(!(func2.call(schema180.properties, key0))){ -const err0 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.part_id !== undefined){ -if(typeof data.part_id !== "string"){ -const err1 = {instancePath:instancePath+"/part_id",schemaPath:"#/properties/part_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.display !== undefined){ -let data1 = data.display; -if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err2 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema180.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key1 in data1){ -if(!(((((key1 === "target") || (key1 === "command")) || (key1 === "query")) || (key1 === "child_id")) || (key1 === "label"))){ -const err3 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data1.target !== undefined){ -if(typeof data1.target !== "string"){ -const err4 = {instancePath:instancePath+"/display/target",schemaPath:"#/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.command !== undefined){ -if(typeof data1.command !== "string"){ -const err5 = {instancePath:instancePath+"/display/command",schemaPath:"#/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.query !== undefined){ -if(typeof data1.query !== "string"){ -const err6 = {instancePath:instancePath+"/display/query",schemaPath:"#/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.child_id !== undefined){ -if(typeof data1.child_id !== "string"){ -const err7 = {instancePath:instancePath+"/display/child_id",schemaPath:"#/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err8 = {instancePath:instancePath+"/display/label",schemaPath:"#/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data7 = data.accounting; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema180.properties.accounting.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.root_id === undefined){ -const err10 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7.agent_id === undefined){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7.scope === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7.revision === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.reported_cost_micros === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.estimated_cost_micros === undefined){ -const err15 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7.reported_cost_calls === undefined){ -const err16 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.estimated_cost_calls === undefined){ -const err17 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.unknown_cost_calls === undefined){ -const err18 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.reported_calls === undefined){ -const err19 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.estimated_calls === undefined){ -const err20 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data7.pending_calls === undefined){ -const err21 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -for(const key2 in data7){ -if(!(func2.call(schema180.properties.accounting.properties, key2))){ -const err22 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err23 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err24 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.scope !== undefined){ -if(typeof data7.scope !== "string"){ -const err25 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.revision !== undefined){ -let data11 = data7.revision; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err26 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err27 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data7.reported_cost_micros !== undefined){ -let data12 = data7.reported_cost_micros; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err29 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err30 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data7.estimated_cost_micros !== undefined){ -let data13 = data7.estimated_cost_micros; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err32 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err33 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -else { -const err34 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data7.reported_cost_calls !== undefined){ -let data14 = data7.reported_cost_calls; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err35 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err36 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -else { -const err37 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data7.estimated_cost_calls !== undefined){ -let data15 = data7.estimated_cost_calls; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err38 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err39 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -else { -const err40 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data7.unknown_cost_calls !== undefined){ -let data16 = data7.unknown_cost_calls; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err41 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err42 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -else { -const err43 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data7.reported_calls !== undefined){ -let data17 = data7.reported_calls; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err44 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err45 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -else { -const err46 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data7.estimated_calls !== undefined){ -let data18 = data7.estimated_calls; -if(typeof data18 === "string"){ -if(!pattern0.test(data18)){ -const err47 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(!(formats0.validate(data18))){ -const err48 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -else { -const err49 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data7.pending_calls !== undefined){ -let data19 = data7.pending_calls; -if(typeof data19 === "string"){ -if(!pattern0.test(data19)){ -const err50 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(!(formats0.validate(data19))){ -const err51 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -else { -const err52 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -} -} -if(data.usage !== undefined){ -let data20 = data.usage; -if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err53 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema180.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.used === undefined){ -const err54 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data20.size === undefined){ -const err55 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data20.usage === undefined){ -const err56 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -for(const key3 in data20){ -if(!(((key3 === "used") || (key3 === "size")) || (key3 === "usage"))){ -const err57 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data20.used !== undefined){ -let data21 = data20.used; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err58 = {instancePath:instancePath+"/usage/used",schemaPath:"#/properties/usage/properties/used/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data20.size !== undefined){ -let data22 = data20.size; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err59 = {instancePath:instancePath+"/usage/size",schemaPath:"#/properties/usage/properties/size/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data20.usage !== undefined){ -let data23 = data20.usage; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt_tokens === undefined){ -const err60 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data23.completion_tokens === undefined){ -const err61 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -for(const key4 in data23){ -if(!((((((key4 === "reported") || (key4 === "cost")) || (key4 === "prompt_tokens")) || (key4 === "completion_tokens")) || (key4 === "prompt_tokens_details")) || (key4 === "completion_tokens_details"))){ -const err62 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data23.reported !== undefined){ -if(typeof data23.reported !== "boolean"){ -const err63 = {instancePath:instancePath+"/usage/usage/reported",schemaPath:"#/properties/usage/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data23.cost !== undefined){ -let data25 = data23.cost; -if((data25 !== null) && (!(typeof data25 == "number"))){ -const err64 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data23.prompt_tokens !== undefined){ -let data26 = data23.prompt_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err65 = {instancePath:instancePath+"/usage/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data23.completion_tokens !== undefined){ -let data27 = data23.completion_tokens; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err66 = {instancePath:instancePath+"/usage/usage/completion_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data23.prompt_tokens_details !== undefined){ -let data28 = data23.prompt_tokens_details; -if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err67 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data28 && typeof data28 == "object" && !Array.isArray(data28)){ -if(data28.cached_tokens === undefined){ -const err68 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -for(const key5 in data28){ -if(!(key5 === "cached_tokens")){ -const err69 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data28.cached_tokens !== undefined){ -let data29 = data28.cached_tokens; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err70 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -} -} -if(data23.completion_tokens_details !== undefined){ -let data30 = data23.completion_tokens_details; -if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err71 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.reasoning_tokens === undefined){ -const err72 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -for(const key6 in data30){ -if(!(key6 === "reasoning_tokens")){ -const err73 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data30.reasoning_tokens !== undefined){ -let data31 = data30.reasoning_tokens; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err74 = {instancePath:instancePath+"/usage/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -} -} -} -else { -const err75 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err76 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err77 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err78 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err79 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data.host_status !== undefined){ -if(typeof data.host_status !== "string"){ -const err80 = {instancePath:instancePath+"/host_status",schemaPath:"#/properties/host_status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err81 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err82 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err83 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data.args !== undefined){ -if(typeof data.args !== "string"){ -const err84 = {instancePath:instancePath+"/args",schemaPath:"#/properties/args/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data.result !== undefined){ -if(typeof data.result !== "string"){ -const err85 = {instancePath:instancePath+"/result",schemaPath:"#/properties/result/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -} -else { -const err86 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -validate179.errors = vErrors; -return errors === 0; -} - -export const SubmitPayload = validate180; -const schema181 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":false}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":false},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":false}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":false}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":false}; - -function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubmitPayload" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "design_context") || (key0 === "text")) || (key0 === "parts")) || (key0 === "attachments"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.design_context !== undefined){ -let data0 = data.design_context; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema181.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.context_attachment_id === undefined){ -const err3 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.elements === undefined){ -const err4 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.element_count === undefined){ -const err5 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -for(const key1 in data0){ -if(!((((((key1 === "context_attachment_id") || (key1 === "screenshot_attachment_id")) || (key1 === "elements")) || (key1 === "element_count")) || (key1 === "page_url")) || (key1 === "page_title"))){ -const err6 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.context_attachment_id !== undefined){ -if(typeof data0.context_attachment_id !== "string"){ -const err7 = {instancePath:instancePath+"/design_context/context_attachment_id",schemaPath:"#/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.screenshot_attachment_id !== undefined){ -if(typeof data0.screenshot_attachment_id !== "string"){ -const err8 = {instancePath:instancePath+"/design_context/screenshot_attachment_id",schemaPath:"#/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.elements !== undefined){ -let data3 = data0.elements; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err9 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema181.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.label === undefined){ -const err10 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -for(const key2 in data4){ -if(!((key2 === "label") || (key2 === "selector"))){ -const err11 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data4.label !== undefined){ -if(typeof data4.label !== "string"){ -const err12 = {instancePath:instancePath+"/design_context/elements/" + i0+"/label",schemaPath:"#/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.selector !== undefined){ -if(typeof data4.selector !== "string"){ -const err13 = {instancePath:instancePath+"/design_context/elements/" + i0+"/selector",schemaPath:"#/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data0.element_count !== undefined){ -let data7 = data0.element_count; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err15 = {instancePath:instancePath+"/design_context/element_count",schemaPath:"#/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data0.page_url !== undefined){ -if(typeof data0.page_url !== "string"){ -const err16 = {instancePath:instancePath+"/design_context/page_url",schemaPath:"#/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data0.page_title !== undefined){ -if(typeof data0.page_title !== "string"){ -const err17 = {instancePath:instancePath+"/design_context/page_title",schemaPath:"#/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err18 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.parts !== undefined){ -let data11 = data.parts; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err19 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema181.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data11)){ -const len1 = data11.length; -for(let i1=0; i1<len1; i1++){ -let data12 = data11[i1]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.type === undefined){ -const err20 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -for(const key3 in data12){ -if(!(((((key3 === "type") || (key3 === "text")) || (key3 === "image_url")) || (key3 === "w")) || (key3 === "h"))){ -const err21 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key3},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data12.type !== undefined){ -if(typeof data12.type !== "string"){ -const err22 = {instancePath:instancePath+"/parts/" + i1+"/type",schemaPath:"#/properties/parts/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data12.text !== undefined){ -if(typeof data12.text !== "string"){ -const err23 = {instancePath:instancePath+"/parts/" + i1+"/text",schemaPath:"#/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data12.image_url !== undefined){ -let data15 = data12.image_url; -if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err24 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema181.properties.parts.items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.url === undefined){ -const err25 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -for(const key4 in data15){ -if(!(key4 === "url")){ -const err26 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key4},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data15.url !== undefined){ -if(typeof data15.url !== "string"){ -const err27 = {instancePath:instancePath+"/parts/" + i1+"/image_url/url",schemaPath:"#/properties/parts/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data12.w !== undefined){ -let data17 = data12.w; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err28 = {instancePath:instancePath+"/parts/" + i1+"/w",schemaPath:"#/properties/parts/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data12.h !== undefined){ -let data18 = data12.h; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err29 = {instancePath:instancePath+"/parts/" + i1+"/h",schemaPath:"#/properties/parts/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -else { -const err30 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -} -if(data.attachments !== undefined){ -let data19 = data.attachments; -if((data19 !== null) && (!(Array.isArray(data19)))){ -const err31 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema181.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(Array.isArray(data19)){ -const len2 = data19.length; -for(let i2=0; i2<len2; i2++){ -let data20 = data19[i2]; -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.kind === undefined){ -const err32 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data20.content === undefined){ -const err33 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -for(const key5 in data20){ -if(!(((key5 === "kind") || (key5 === "content")) || (key5 === "name"))){ -const err34 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key5},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data20.kind !== undefined){ -let data21 = data20.kind; -if(typeof data21 !== "string"){ -const err35 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(!((data21 === "image") || (data21 === "text"))){ -const err36 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema181.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data20.content !== undefined){ -let data22 = data20.content; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.reference_id === undefined){ -const err37 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data22.digest === undefined){ -const err38 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data22.size === undefined){ -const err39 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -for(const key6 in data22){ -if(!(((((key6 === "reference_id") || (key6 === "digest")) || (key6 === "size")) || (key6 === "media_type")) || (key6 === "source"))){ -const err40 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key6},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data22.reference_id !== undefined){ -if(typeof data22.reference_id !== "string"){ -const err41 = {instancePath:instancePath+"/attachments/" + i2+"/content/reference_id",schemaPath:"#/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data22.digest !== undefined){ -if(typeof data22.digest !== "string"){ -const err42 = {instancePath:instancePath+"/attachments/" + i2+"/content/digest",schemaPath:"#/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data22.size !== undefined){ -let data25 = data22.size; -if(typeof data25 === "string"){ -if(!pattern0.test(data25)){ -const err43 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data25))){ -const err44 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data22.media_type !== undefined){ -if(typeof data22.media_type !== "string"){ -const err46 = {instancePath:instancePath+"/attachments/" + i2+"/content/media_type",schemaPath:"#/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data22.source !== undefined){ -if(typeof data22.source !== "string"){ -const err47 = {instancePath:instancePath+"/attachments/" + i2+"/content/source",schemaPath:"#/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -else { -const err48 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data20.name !== undefined){ -if(typeof data20.name !== "string"){ -const err49 = {instancePath:instancePath+"/attachments/" + i2+"/name",schemaPath:"#/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -} -else { -const err50 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -} -} -else { -const err51 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -validate180.errors = vErrors; -return errors === 0; -} - -export const SubscribeParams = validate181; -const schema182 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":false}; - -function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscribeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.subscription_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cursor === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "root_id") || (key0 === "subscription_id")) || (key0 === "cursor"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err5 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate181.errors = vErrors; -return errors === 0; -} - -export const SubscribeResult = validate182; -const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":false}; - -function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscribeResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "subscription_id") || (key0 === "cursor"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err3 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate182.errors = vErrors; -return errors === 0; -} - -export const SubscriptionFailure = validate183; -const schema184 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":false},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":false}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":false}; - -function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscriptionFailure" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.error === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "error"},message:"must have required property '"+"error"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "subscription_id") || (key0 === "root_id")) || (key0 === "error"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err4 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.error !== undefined){ -let data2 = data.error; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err6 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema184.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.code === undefined){ -const err7 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.message === undefined){ -const err8 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -for(const key1 in data2){ -if(!(((key1 === "data") || (key1 === "code")) || (key1 === "message"))){ -const err9 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data2.data !== undefined){ -let data3 = data2.data; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err10 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema184.properties.error.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.kind === undefined){ -const err11 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -for(const key2 in data3){ -if(!(key2 === "kind")){ -const err12 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key2},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data3.kind !== undefined){ -if(typeof data3.kind !== "string"){ -const err13 = {instancePath:instancePath+"/error/data/kind",schemaPath:"#/properties/error/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -} -if(data2.code !== undefined){ -let data5 = data2.code; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err14 = {instancePath:instancePath+"/error/code",schemaPath:"#/properties/error/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data2.message !== undefined){ -if(typeof data2.message !== "string"){ -const err15 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -} -else { -const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -validate183.errors = vErrors; -return errors === 0; -} - -export const TerminalAttachParams = validate184; -const schema185 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":false}; - -function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "cursor"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate184.errors = vErrors; -return errors === 0; -} - -export const TerminalAttachResult = validate185; -const schema186 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":false}; - -function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cursor === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cwd === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cols === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.rows === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.exited === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "exited"},message:"must have required property '"+"exited"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "cursor") || (key0 === "cwd")) || (key0 === "cols")) || (key0 === "rows")) || (key0 === "exited")) || (key0 === "exit_code")) || (key0 === "signal"))){ -const err5 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data0 = data.cursor; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err9 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.cols !== undefined){ -let data2 = data.cols; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err10 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.rows !== undefined){ -let data3 = data.rows; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err11 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.exited !== undefined){ -if(typeof data.exited !== "boolean"){ -const err12 = {instancePath:instancePath+"/exited",schemaPath:"#/properties/exited/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.exit_code !== undefined){ -let data5 = data.exit_code; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err13 = {instancePath:instancePath+"/exit_code",schemaPath:"#/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.signal !== undefined){ -if(typeof data.signal !== "string"){ -const err14 = {instancePath:instancePath+"/signal",schemaPath:"#/properties/signal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -validate185.errors = vErrors; -return errors === 0; -} - -export const TerminalDetachedParams = validate186; -const schema187 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":false}; - -function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalDetachedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate186.errors = vErrors; -return errors === 0; -} - -export const TerminalExitedParams = validate187; -const schema188 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":false}; - -function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalExitedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.exit_code === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "exit_code"},message:"must have required property '"+"exit_code"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "exit_code")) || (key0 === "signal"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.exit_code !== undefined){ -let data1 = data.exit_code; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err4 = {instancePath:instancePath+"/exit_code",schemaPath:"#/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.signal !== undefined){ -if(typeof data.signal !== "string"){ -const err5 = {instancePath:instancePath+"/signal",schemaPath:"#/properties/signal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate187.errors = vErrors; -return errors === 0; -} - -export const TerminalIDParams = validate188; -const schema189 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":false}; - -function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalIDParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate188.errors = vErrors; -return errors === 0; -} - -export const TerminalInputParams = validate189; -const schema190 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":false}; - -function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalInputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "bytes"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data1 = data.bytes; -if((typeof data1 !== "string") && (data1 !== null)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema190.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern52.test(data1)){ -const err5 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate189.errors = vErrors; -return errors === 0; -} - -export const TerminalOpenParams = validate190; -const schema191 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":false}; - -function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cols === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.rows === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "cwd") || (key0 === "root_id")) || (key0 === "cols")) || (key0 === "rows"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err3 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cols !== undefined){ -let data2 = data.cols; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.rows !== undefined){ -let data3 = data.rows; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err6 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate190.errors = vErrors; -return errors === 0; -} - -export const TerminalOpenResult = validate191; -const schema192 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":false}; - -function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.shell === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "shell"},message:"must have required property '"+"shell"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cwd === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "shell")) || (key0 === "cwd"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.shell !== undefined){ -if(typeof data.shell !== "string"){ -const err5 = {instancePath:instancePath+"/shell",schemaPath:"#/properties/shell/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err6 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate191.errors = vErrors; -return errors === 0; -} - -export const TerminalOutputParams = validate192; -const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":false}; - -function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOutputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.bytes === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "cursor")) || (key0 === "bytes"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data2 = data.bytes; -if((typeof data2 !== "string") && (data2 !== null)){ -const err8 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema193.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(typeof data2 === "string"){ -if(!pattern52.test(data2)){ -const err9 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate192.errors = vErrors; -return errors === 0; -} - -export const TerminalResizeParams = validate193; -const schema194 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":false}; - -function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalResizeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cols === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.rows === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "id") || (key0 === "cols")) || (key0 === "rows"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err4 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cols !== undefined){ -let data1 = data.cols; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err5 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.rows !== undefined){ -let data2 = data.rows; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err6 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate193.errors = vErrors; -return errors === 0; -} - -export const TerminalWriteParams = validate194; -const schema195 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":false}; - -function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalWriteParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "id") || (key0 === "bytes"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data1 = data.bytes; -if((typeof data1 !== "string") && (data1 !== null)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema195.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern52.test(data1)){ -const err5 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate194.errors = vErrors; -return errors === 0; -} - -export const TextParams = validate195; -const schema196 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":false}; - -function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TextParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "text")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err2 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate195.errors = vErrors; -return errors === 0; -} - -export const TextResult = validate196; -const schema197 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":false}; - -function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TextResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "text") || (key0 === "output"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err2 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate196.errors = vErrors; -return errors === 0; -} - -export const TitleParams = validate197; -const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":false}; - -function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TitleParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.title === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "title")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err2 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate197.errors = vErrors; -return errors === 0; -} - -export const TitleResult = validate198; -const schema199 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":false}; - -function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TitleResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.title === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "title")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err2 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate198.errors = vErrors; -return errors === 0; -} - -export const ToolCallParams = validate199; -const schema200 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":false}; - -function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolCallParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.tool === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.arguments === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "tool") || (key0 === "arguments"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.tool !== undefined){ -if(typeof data.tool !== "string"){ -const err3 = {instancePath:instancePath+"/tool",schemaPath:"#/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate199.errors = vErrors; -return errors === 0; -} - -export const ToolCancelParams = validate200; -const schema201 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":false}; - -function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolCancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.reason === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "invocation_id") || (key0 === "generation")) || (key0 === "reason"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err4 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err8 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate200.errors = vErrors; -return errors === 0; -} - -export const ToolConfigureParams = validate201; -const schema202 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":false}; - -function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.deny_permissions === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deny_permissions"},message:"must have required property '"+"deny_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "deny_permissions")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.deny_permissions !== undefined){ -if(typeof data.deny_permissions !== "boolean"){ -const err2 = {instancePath:instancePath+"/deny_permissions",schemaPath:"#/properties/deny_permissions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate201.errors = vErrors; -return errors === 0; -} - -export const ToolInvokeParams = validate202; -const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":false}; - -function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolInvokeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.definition === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.agent_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.turn_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.tool === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.input === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "input"},message:"must have required property '"+"input"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -for(const key0 in data){ -if(!(func2.call(schema203.properties, key0))){ -const err10 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err11 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err13 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.generation !== undefined){ -let data3 = data.generation; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err14 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err15 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -else { -const err16 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err17 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err18 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err19 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.tool !== undefined){ -if(typeof data.tool !== "string"){ -const err20 = {instancePath:instancePath+"/tool",schemaPath:"#/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data8 = data.deadline_millis; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err21 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err22 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -validate202.errors = vErrors; -return errors === 0; -} - -export const ToolProgressParams = validate203; -const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":false}; - -function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolProgressParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.text === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "invocation_id") || (key0 === "generation")) || (key0 === "text"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err4 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err8 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate203.errors = vErrors; -return errors === 0; -} - -export const ToolResultParams = validate204; -const schema205 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":false}; - -function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -for(const key0 in data){ -if(!((((key0 === "invocation_id") || (key0 === "generation")) || (key0 === "output")) || (key0 === "error"))){ -const err2 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err3 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err7 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate204.errors = vErrors; -return errors === 0; -} - -export const ToolSchemaResult = validate205; -const schema206 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":false}},"required":["type","function"],"additionalProperties":false},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; - -function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolSchemaResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema206.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.type === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.function === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data0){ -if(!((key0 === "type") || (key0 === "function"))){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.type !== undefined){ -if(typeof data0.type !== "string"){ -const err4 = {instancePath:instancePath+"/" + i0+"/type",schemaPath:"#/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.function !== undefined){ -let data2 = data0.function; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err5 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2.description === undefined){ -const err6 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2.parameters === undefined){ -const err7 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "parameters"},message:"must have required property '"+"parameters"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -for(const key1 in data2){ -if(!(((key1 === "name") || (key1 === "description")) || (key1 === "parameters"))){ -const err8 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err9 = {instancePath:instancePath+"/" + i0+"/function/name",schemaPath:"#/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data2.description !== undefined){ -if(typeof data2.description !== "string"){ -const err10 = {instancePath:instancePath+"/" + i0+"/function/description",schemaPath:"#/items/properties/function/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -validate205.errors = vErrors; -return errors === 0; -} - -export const TraceExportParams = validate206; -const schema207 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":false}; - -function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TraceExportParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!((key0 === "root_id") || (key0 === "trace_id"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err3 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate206.errors = vErrors; -return errors === 0; -} - -export const TraceExportResult = validate207; -const schema208 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":false},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":false}; - -function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TraceExportResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.content === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.spans === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "spans"},message:"must have required property '"+"spans"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.traces === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "traces"},message:"must have required property '"+"traces"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "content") || (key0 === "spans")) || (key0 === "traces"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.content !== undefined){ -let data0 = data.content; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err4 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.digest === undefined){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.size === undefined){ -const err6 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -for(const key1 in data0){ -if(!(((((key1 === "reference_id") || (key1 === "digest")) || (key1 === "size")) || (key1 === "media_type")) || (key1 === "source"))){ -const err7 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key1},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err8 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err9 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err10 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err11 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -else { -const err12 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err13 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err14 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.spans !== undefined){ -let data6 = data.spans; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err16 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.traces !== undefined){ -let data7 = data.traces; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err17 = {instancePath:instancePath+"/traces",schemaPath:"#/properties/traces/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -validate207.errors = vErrors; -return errors === 0; -} - -export const TracePageParams = validate208; -const schema209 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":false}; - -function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TracePageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(((((key0 === "root_id") || (key0 === "trace_id")) || (key0 === "after_seq")) || (key0 === "limit")) || (key0 === "roots_only"))){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err3 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.after_seq !== undefined){ -let data2 = data.after_seq; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err4 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err5 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.limit !== undefined){ -let data3 = data.limit; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err7 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.roots_only !== undefined){ -if(typeof data.roots_only !== "boolean"){ -const err8 = {instancePath:instancePath+"/roots_only",schemaPath:"#/properties/roots_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate208.errors = vErrors; -return errors === 0; -} - -export const UnsubscribeParams = validate209; -const schema210 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":false}; - -function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UnsubscribeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "subscription_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err2 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate209.errors = vErrors; -return errors === 0; -} - -export const UploadBeginParams = validate210; -const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":false}; - -function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadBeginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.expected_digest === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_digest"},message:"must have required property '"+"expected_digest"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.size === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -for(const key0 in data){ -if(!(((((((key0 === "upload_id") || (key0 === "root_id")) || (key0 === "agent_id")) || (key0 === "expected_digest")) || (key0 === "size")) || (key0 === "media_type")) || (key0 === "source"))){ -const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err5 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err7 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.expected_digest !== undefined){ -if(typeof data.expected_digest !== "string"){ -const err8 = {instancePath:instancePath+"/expected_digest",schemaPath:"#/properties/expected_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.size !== undefined){ -let data4 = data.size; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err9 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err10 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.media_type !== undefined){ -if(typeof data.media_type !== "string"){ -const err12 = {instancePath:instancePath+"/media_type",schemaPath:"#/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err13 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -validate210.errors = vErrors; -return errors === 0; -} - -export const UploadChunkParams = validate211; -const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":false}; - -function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadChunkParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.offset === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.data === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "data"},message:"must have required property '"+"data"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -for(const key0 in data){ -if(!(((key0 === "upload_id") || (key0 === "offset")) || (key0 === "data"))){ -const err3 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err4 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.offset !== undefined){ -let data1 = data.offset; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err5 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err6 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.data !== undefined){ -let data2 = data.data; -if((typeof data2 !== "string") && (data2 !== null)){ -const err8 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema212.properties.data.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(typeof data2 === "string"){ -if(!pattern52.test(data2)){ -const err9 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate211.errors = vErrors; -return errors === 0; -} - -export const UploadFinishParams = validate212; -const schema213 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":false}; - -function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadFinishParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -for(const key0 in data){ -if(!(key0 === "upload_id")){ -const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err2 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate212.errors = vErrors; -return errors === 0; -} - -export const UserHistoryResult = validate213; -const schema214 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; - -function validate213(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UserHistoryResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema214.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data[i0] !== "string"){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -validate213.errors = vErrors; -return errors === 0; -} diff --git a/packages/protocol/generated/response-validators.js b/packages/protocol/generated/response-validators.js deleted file mode 100644 index 9066220d2..000000000 --- a/packages/protocol/generated/response-validators.js +++ /dev/null @@ -1,66788 +0,0 @@ -// Generated standalone validators. Run npm run generate. -"use strict"; -export const Accepted = validate10; -const schema11 = {"type":"object","properties":{"accepted":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/Accepted","$schema":"http://json-schema.org/draft-07/schema#","title":"Accepted","required":["accepted"],"additionalProperties":true}; - -function validate10(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Accepted" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.accepted === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "accepted"},message:"must have required property '"+"accepted"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.accepted !== undefined){ -if(typeof data.accepted !== "boolean"){ -const err1 = {instancePath:instancePath+"/accepted",schemaPath:"#/properties/accepted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate10.errors = vErrors; -return errors === 0; -} - -export const AgentCancelParams = validate11; -const schema12 = {"type":"object","properties":{"id":{"type":"string"},"turn_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/AgentCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentCancelParams","required":["id","turn_id"],"additionalProperties":true}; - -function validate11(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentCancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.turn_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err3 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate11.errors = vErrors; -return errors === 0; -} - -export const AgentInputParams = validate12; -const schema13 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"id":{"type":"string"},"text":{"type":"string"},"delivery":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/AgentInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentInputParams","required":["id","text"],"additionalProperties":true}; -const formats0 = {int64: {type: 'string', validate: value => { - if (!/^-?(0|[1-9][0-9]*)$/.test(value) || value.length > 20) return false; - const number = BigInt(value); - return number >= -9223372036854775808n && number <= 9223372036854775807n; -}}}.int64; -const pattern0 = new RegExp("^-?(0|[1-9][0-9]*)$", "u"); - -function validate12(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentInputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.text === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.design_context !== undefined){ -let data0 = data.design_context; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema13.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.context_attachment_id === undefined){ -const err3 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.elements === undefined){ -const err4 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.element_count === undefined){ -const err5 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.context_attachment_id !== undefined){ -if(typeof data0.context_attachment_id !== "string"){ -const err6 = {instancePath:instancePath+"/design_context/context_attachment_id",schemaPath:"#/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.screenshot_attachment_id !== undefined){ -if(typeof data0.screenshot_attachment_id !== "string"){ -const err7 = {instancePath:instancePath+"/design_context/screenshot_attachment_id",schemaPath:"#/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.elements !== undefined){ -let data3 = data0.elements; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema13.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.label === undefined){ -const err9 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.label !== undefined){ -if(typeof data4.label !== "string"){ -const err10 = {instancePath:instancePath+"/design_context/elements/" + i0+"/label",schemaPath:"#/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data4.selector !== undefined){ -if(typeof data4.selector !== "string"){ -const err11 = {instancePath:instancePath+"/design_context/elements/" + i0+"/selector",schemaPath:"#/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data0.element_count !== undefined){ -let data7 = data0.element_count; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err13 = {instancePath:instancePath+"/design_context/element_count",schemaPath:"#/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data0.page_url !== undefined){ -if(typeof data0.page_url !== "string"){ -const err14 = {instancePath:instancePath+"/design_context/page_url",schemaPath:"#/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data0.page_title !== undefined){ -if(typeof data0.page_title !== "string"){ -const err15 = {instancePath:instancePath+"/design_context/page_title",schemaPath:"#/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err16 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err17 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err18 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.parts !== undefined){ -let data13 = data.parts; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err19 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema13.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data13)){ -const len1 = data13.length; -for(let i1=0; i1<len1; i1++){ -let data14 = data13[i1]; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.type === undefined){ -const err20 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data14.type !== undefined){ -if(typeof data14.type !== "string"){ -const err21 = {instancePath:instancePath+"/parts/" + i1+"/type",schemaPath:"#/properties/parts/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data14.text !== undefined){ -if(typeof data14.text !== "string"){ -const err22 = {instancePath:instancePath+"/parts/" + i1+"/text",schemaPath:"#/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data14.image_url !== undefined){ -let data17 = data14.image_url; -if((data17 !== null) && (!(data17 && typeof data17 == "object" && !Array.isArray(data17)))){ -const err23 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema13.properties.parts.items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.url === undefined){ -const err24 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data17.url !== undefined){ -if(typeof data17.url !== "string"){ -const err25 = {instancePath:instancePath+"/parts/" + i1+"/image_url/url",schemaPath:"#/properties/parts/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data14.w !== undefined){ -let data19 = data14.w; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err26 = {instancePath:instancePath+"/parts/" + i1+"/w",schemaPath:"#/properties/parts/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data14.h !== undefined){ -let data20 = data14.h; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err27 = {instancePath:instancePath+"/parts/" + i1+"/h",schemaPath:"#/properties/parts/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -else { -const err28 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -if(data.attachments !== undefined){ -let data21 = data.attachments; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err29 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema13.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(Array.isArray(data21)){ -const len2 = data21.length; -for(let i2=0; i2<len2; i2++){ -let data22 = data21[i2]; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.kind === undefined){ -const err30 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data22.content === undefined){ -const err31 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data22.kind !== undefined){ -let data23 = data22.kind; -if(typeof data23 !== "string"){ -const err32 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!((data23 === "image") || (data23 === "text"))){ -const err33 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema13.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data22.content !== undefined){ -let data24 = data22.content; -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.reference_id === undefined){ -const err34 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data24.digest === undefined){ -const err35 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data24.size === undefined){ -const err36 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data24.reference_id !== undefined){ -if(typeof data24.reference_id !== "string"){ -const err37 = {instancePath:instancePath+"/attachments/" + i2+"/content/reference_id",schemaPath:"#/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data24.digest !== undefined){ -if(typeof data24.digest !== "string"){ -const err38 = {instancePath:instancePath+"/attachments/" + i2+"/content/digest",schemaPath:"#/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data24.size !== undefined){ -let data27 = data24.size; -if(typeof data27 === "string"){ -if(!pattern0.test(data27)){ -const err39 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(!(formats0.validate(data27))){ -const err40 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -else { -const err41 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data24.media_type !== undefined){ -if(typeof data24.media_type !== "string"){ -const err42 = {instancePath:instancePath+"/attachments/" + i2+"/content/media_type",schemaPath:"#/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data24.source !== undefined){ -if(typeof data24.source !== "string"){ -const err43 = {instancePath:instancePath+"/attachments/" + i2+"/content/source",schemaPath:"#/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -else { -const err44 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data22.name !== undefined){ -if(typeof data22.name !== "string"){ -const err45 = {instancePath:instancePath+"/attachments/" + i2+"/name",schemaPath:"#/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -else { -const err46 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -} -} -else { -const err47 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -validate12.errors = vErrors; -return errors === 0; -} - -export const AgentListResult = validate13; -const schema14 = {"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":true},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/AgentListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentListResult"}; - -function validate13(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema14.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.execution_engine === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.id === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.root_id === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.parent_id === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.name === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.model === undefined){ -const err6 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.provider === undefined){ -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.effort === undefined){ -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.cwd === undefined){ -const err9 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.report === undefined){ -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.status === undefined){ -const err11 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.pending_mail === undefined){ -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.lifecycle_phase === undefined){ -const err13 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.blocking_reason === undefined){ -const err14 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.terminal_cause === undefined){ -const err15 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.allowed_controls === undefined){ -const err16 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data0.execution_engine !== undefined){ -if(typeof data0.execution_engine !== "string"){ -const err17 = {instancePath:instancePath+"/" + i0+"/execution_engine",schemaPath:"#/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.last_turn !== undefined){ -let data2 = data0.last_turn; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err18 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/type",keyword:"type",params:{type: schema14.items.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.status === undefined){ -const err19 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2.event_seq === undefined){ -const err20 = {instancePath:instancePath+"/" + i0+"/last_turn",schemaPath:"#/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.turn_id !== undefined){ -if(typeof data2.turn_id !== "string"){ -const err21 = {instancePath:instancePath+"/" + i0+"/last_turn/turn_id",schemaPath:"#/items/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err22 = {instancePath:instancePath+"/" + i0+"/last_turn/status",schemaPath:"#/items/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.started_at !== undefined){ -if(typeof data2.started_at !== "string"){ -const err23 = {instancePath:instancePath+"/" + i0+"/last_turn/started_at",schemaPath:"#/items/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.finished_at !== undefined){ -if(typeof data2.finished_at !== "string"){ -const err24 = {instancePath:instancePath+"/" + i0+"/last_turn/finished_at",schemaPath:"#/items/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.event_seq !== undefined){ -let data7 = data2.event_seq; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err25 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err26 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -else { -const err27 = {instancePath:instancePath+"/" + i0+"/last_turn/event_seq",schemaPath:"#/items/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.error !== undefined){ -if(typeof data2.error !== "string"){ -const err28 = {instancePath:instancePath+"/" + i0+"/last_turn/error",schemaPath:"#/items/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data2.error_truncated !== undefined){ -if(typeof data2.error_truncated !== "boolean"){ -const err29 = {instancePath:instancePath+"/" + i0+"/last_turn/error_truncated",schemaPath:"#/items/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data2.error_details !== undefined){ -let data10 = data2.error_details; -if((data10 !== null) && (!(data10 && typeof data10 == "object" && !Array.isArray(data10)))){ -const err30 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.reference_id === undefined){ -const err31 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data10.digest === undefined){ -const err32 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data10.size === undefined){ -const err33 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data10.media_type === undefined){ -const err34 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data10.source === undefined){ -const err35 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details",schemaPath:"#/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data10.text !== undefined){ -let data11 = data10.text; -if((data11 !== null) && (typeof data11 !== "string")){ -const err36 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/text",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data10.binary !== undefined){ -let data12 = data10.binary; -if((typeof data12 !== "string") && (data12 !== null)){ -const err37 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/binary",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema14.items.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data10.reference_id !== undefined){ -if(typeof data10.reference_id !== "string"){ -const err38 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/reference_id",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data10.digest !== undefined){ -if(typeof data10.digest !== "string"){ -const err39 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/digest",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data10.size !== undefined){ -let data15 = data10.size; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err40 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err41 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/size",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data10.media_type !== undefined){ -if(typeof data10.media_type !== "string"){ -const err43 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/media_type",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data10.source !== undefined){ -if(typeof data10.source !== "string"){ -const err44 = {instancePath:instancePath+"/" + i0+"/last_turn/error_details/source",schemaPath:"#/items/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -} -if(data2.model_calls !== undefined){ -let data18 = data2.model_calls; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err45 = {instancePath:instancePath+"/" + i0+"/last_turn/model_calls",schemaPath:"#/items/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data2.compactions !== undefined){ -let data19 = data2.compactions; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err46 = {instancePath:instancePath+"/" + i0+"/last_turn/compactions",schemaPath:"#/items/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data2.last_activity_at !== undefined){ -if(typeof data2.last_activity_at !== "string"){ -const err47 = {instancePath:instancePath+"/" + i0+"/last_turn/last_activity_at",schemaPath:"#/items/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err48 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err49 = {instancePath:instancePath+"/" + i0+"/root_id",schemaPath:"#/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data0.parent_id !== undefined){ -if(typeof data0.parent_id !== "string"){ -const err50 = {instancePath:instancePath+"/" + i0+"/parent_id",schemaPath:"#/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err51 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data0.model !== undefined){ -if(typeof data0.model !== "string"){ -const err52 = {instancePath:instancePath+"/" + i0+"/model",schemaPath:"#/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data0.provider !== undefined){ -if(typeof data0.provider !== "string"){ -const err53 = {instancePath:instancePath+"/" + i0+"/provider",schemaPath:"#/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data0.effort !== undefined){ -if(typeof data0.effort !== "string"){ -const err54 = {instancePath:instancePath+"/" + i0+"/effort",schemaPath:"#/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data0.cwd !== undefined){ -if(typeof data0.cwd !== "string"){ -const err55 = {instancePath:instancePath+"/" + i0+"/cwd",schemaPath:"#/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data0.report !== undefined){ -if(typeof data0.report !== "string"){ -const err56 = {instancePath:instancePath+"/" + i0+"/report",schemaPath:"#/items/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data0.status !== undefined){ -if(typeof data0.status !== "string"){ -const err57 = {instancePath:instancePath+"/" + i0+"/status",schemaPath:"#/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data0.pending_mail !== undefined){ -let data31 = data0.pending_mail; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err58 = {instancePath:instancePath+"/" + i0+"/pending_mail",schemaPath:"#/items/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data0.lifecycle_phase !== undefined){ -if(typeof data0.lifecycle_phase !== "string"){ -const err59 = {instancePath:instancePath+"/" + i0+"/lifecycle_phase",schemaPath:"#/items/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data0.blocking_reason !== undefined){ -if(typeof data0.blocking_reason !== "string"){ -const err60 = {instancePath:instancePath+"/" + i0+"/blocking_reason",schemaPath:"#/items/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data0.terminal_cause !== undefined){ -if(typeof data0.terminal_cause !== "string"){ -const err61 = {instancePath:instancePath+"/" + i0+"/terminal_cause",schemaPath:"#/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data0.allowed_controls !== undefined){ -let data35 = data0.allowed_controls; -if((data35 !== null) && (!(Array.isArray(data35)))){ -const err62 = {instancePath:instancePath+"/" + i0+"/allowed_controls",schemaPath:"#/items/properties/allowed_controls/type",keyword:"type",params:{type: schema14.items.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(Array.isArray(data35)){ -const len1 = data35.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data35[i1] !== "string"){ -const err63 = {instancePath:instancePath+"/" + i0+"/allowed_controls/" + i1,schemaPath:"#/items/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -} -} -} -else { -const err64 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -validate13.errors = vErrors; -return errors === 0; -} - -export const AgentSubmitResult = validate14; -const schema15 = {"type":"object","properties":{"agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/AgentSubmitResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentSubmitResult","required":["agent_id","inbox_seq","status"],"additionalProperties":true}; - -function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentSubmitResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.agent_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.status === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err3 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err7 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err8 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate14.errors = vErrors; -return errors === 0; -} - -export const AgentTranscriptResult = validate15; -const schema16 = {"type":"object","properties":{"accounting":{"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"agent":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":true},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":true},"page":{"type":"object","properties":{"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"through_seq":{"type":"integer"},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":true},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true}},"required":["invocation_id","name","status"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":true},"role":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"seq":{"type":"integer"},"message":{"type":["null","object"],"properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":true},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true}},"required":["invocation_id","name","status"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":true},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":true},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":true}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":true},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["seq"],"additionalProperties":true}}},"required":["history_revision","through_seq","next_seq","has_more","messages"],"additionalProperties":true},"presentation":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":true}},"inbox":{"type":["null","array"],"items":{"type":"object","properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["kind","content"],"additionalProperties":true}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":true},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/AgentTranscriptResult","$schema":"http://json-schema.org/draft-07/schema#","title":"AgentTranscriptResult","required":["cursor","agent","page"],"additionalProperties":true}; - -function validate15(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/AgentTranscriptResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cursor === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent"},message:"must have required property '"+"agent"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.page === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "page"},message:"must have required property '"+"page"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.accounting !== undefined){ -let data0 = data.accounting; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.root_id === undefined){ -const err3 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.agent_id === undefined){ -const err4 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.scope === undefined){ -const err5 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.revision === undefined){ -const err6 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.reported_cost_micros === undefined){ -const err7 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.estimated_cost_micros === undefined){ -const err8 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.reported_cost_calls === undefined){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.estimated_cost_calls === undefined){ -const err10 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.unknown_cost_calls === undefined){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.reported_calls === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.estimated_calls === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.pending_calls === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err15 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data0.agent_id !== undefined){ -if(typeof data0.agent_id !== "string"){ -const err16 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data0.scope !== undefined){ -if(typeof data0.scope !== "string"){ -const err17 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.revision !== undefined){ -let data4 = data0.revision; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err18 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err19 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -else { -const err20 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data0.reported_cost_micros !== undefined){ -let data5 = data0.reported_cost_micros; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err21 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err22 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data0.estimated_cost_micros !== undefined){ -let data6 = data0.estimated_cost_micros; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err24 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err25 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data0.reported_cost_calls !== undefined){ -let data7 = data0.reported_cost_calls; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err27 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err28 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -else { -const err29 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data0.estimated_cost_calls !== undefined){ -let data8 = data0.estimated_cost_calls; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err30 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err31 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -else { -const err32 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data0.unknown_cost_calls !== undefined){ -let data9 = data0.unknown_cost_calls; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err33 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err34 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -else { -const err35 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data0.reported_calls !== undefined){ -let data10 = data0.reported_calls; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err36 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err37 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -else { -const err38 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data0.estimated_calls !== undefined){ -let data11 = data0.estimated_calls; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err39 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err40 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -else { -const err41 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data0.pending_calls !== undefined){ -let data12 = data0.pending_calls; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err42 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err43 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -else { -const err44 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -else { -const err45 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data13 = data.cursor; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err46 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err47 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -else { -const err48 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data.agent !== undefined){ -let data14 = data.agent; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.execution_engine === undefined){ -const err49 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data14.id === undefined){ -const err50 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data14.root_id === undefined){ -const err51 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data14.parent_id === undefined){ -const err52 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data14.name === undefined){ -const err53 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data14.model === undefined){ -const err54 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data14.provider === undefined){ -const err55 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data14.effort === undefined){ -const err56 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data14.cwd === undefined){ -const err57 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data14.report === undefined){ -const err58 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data14.status === undefined){ -const err59 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data14.pending_mail === undefined){ -const err60 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data14.lifecycle_phase === undefined){ -const err61 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data14.blocking_reason === undefined){ -const err62 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data14.terminal_cause === undefined){ -const err63 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data14.allowed_controls === undefined){ -const err64 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data14.execution_engine !== undefined){ -if(typeof data14.execution_engine !== "string"){ -const err65 = {instancePath:instancePath+"/agent/execution_engine",schemaPath:"#/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data14.last_turn !== undefined){ -let data16 = data14.last_turn; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err66 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.status === undefined){ -const err67 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data16.event_seq === undefined){ -const err68 = {instancePath:instancePath+"/agent/last_turn",schemaPath:"#/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data16.turn_id !== undefined){ -if(typeof data16.turn_id !== "string"){ -const err69 = {instancePath:instancePath+"/agent/last_turn/turn_id",schemaPath:"#/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data16.status !== undefined){ -if(typeof data16.status !== "string"){ -const err70 = {instancePath:instancePath+"/agent/last_turn/status",schemaPath:"#/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data16.started_at !== undefined){ -if(typeof data16.started_at !== "string"){ -const err71 = {instancePath:instancePath+"/agent/last_turn/started_at",schemaPath:"#/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data16.finished_at !== undefined){ -if(typeof data16.finished_at !== "string"){ -const err72 = {instancePath:instancePath+"/agent/last_turn/finished_at",schemaPath:"#/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data16.event_seq !== undefined){ -let data21 = data16.event_seq; -if(typeof data21 === "string"){ -if(!pattern0.test(data21)){ -const err73 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(!(formats0.validate(data21))){ -const err74 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -else { -const err75 = {instancePath:instancePath+"/agent/last_turn/event_seq",schemaPath:"#/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data16.error !== undefined){ -if(typeof data16.error !== "string"){ -const err76 = {instancePath:instancePath+"/agent/last_turn/error",schemaPath:"#/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data16.error_truncated !== undefined){ -if(typeof data16.error_truncated !== "boolean"){ -const err77 = {instancePath:instancePath+"/agent/last_turn/error_truncated",schemaPath:"#/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data16.error_details !== undefined){ -let data24 = data16.error_details; -if((data24 !== null) && (!(data24 && typeof data24 == "object" && !Array.isArray(data24)))){ -const err78 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.reference_id === undefined){ -const err79 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data24.digest === undefined){ -const err80 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(data24.size === undefined){ -const err81 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data24.media_type === undefined){ -const err82 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data24.source === undefined){ -const err83 = {instancePath:instancePath+"/agent/last_turn/error_details",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data24.text !== undefined){ -let data25 = data24.text; -if((data25 !== null) && (typeof data25 !== "string")){ -const err84 = {instancePath:instancePath+"/agent/last_turn/error_details/text",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data24.binary !== undefined){ -let data26 = data24.binary; -if((typeof data26 !== "string") && (data26 !== null)){ -const err85 = {instancePath:instancePath+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema16.properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data24.reference_id !== undefined){ -if(typeof data24.reference_id !== "string"){ -const err86 = {instancePath:instancePath+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data24.digest !== undefined){ -if(typeof data24.digest !== "string"){ -const err87 = {instancePath:instancePath+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data24.size !== undefined){ -let data29 = data24.size; -if(typeof data29 === "string"){ -if(!pattern0.test(data29)){ -const err88 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(!(formats0.validate(data29))){ -const err89 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -else { -const err90 = {instancePath:instancePath+"/agent/last_turn/error_details/size",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data24.media_type !== undefined){ -if(typeof data24.media_type !== "string"){ -const err91 = {instancePath:instancePath+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data24.source !== undefined){ -if(typeof data24.source !== "string"){ -const err92 = {instancePath:instancePath+"/agent/last_turn/error_details/source",schemaPath:"#/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -} -if(data16.model_calls !== undefined){ -let data32 = data16.model_calls; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err93 = {instancePath:instancePath+"/agent/last_turn/model_calls",schemaPath:"#/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data16.compactions !== undefined){ -let data33 = data16.compactions; -if(!((typeof data33 == "number") && (!(data33 % 1) && !isNaN(data33)))){ -const err94 = {instancePath:instancePath+"/agent/last_turn/compactions",schemaPath:"#/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data16.last_activity_at !== undefined){ -if(typeof data16.last_activity_at !== "string"){ -const err95 = {instancePath:instancePath+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -} -} -if(data14.id !== undefined){ -if(typeof data14.id !== "string"){ -const err96 = {instancePath:instancePath+"/agent/id",schemaPath:"#/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data14.root_id !== undefined){ -if(typeof data14.root_id !== "string"){ -const err97 = {instancePath:instancePath+"/agent/root_id",schemaPath:"#/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data14.parent_id !== undefined){ -if(typeof data14.parent_id !== "string"){ -const err98 = {instancePath:instancePath+"/agent/parent_id",schemaPath:"#/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data14.name !== undefined){ -if(typeof data14.name !== "string"){ -const err99 = {instancePath:instancePath+"/agent/name",schemaPath:"#/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data14.model !== undefined){ -if(typeof data14.model !== "string"){ -const err100 = {instancePath:instancePath+"/agent/model",schemaPath:"#/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data14.provider !== undefined){ -if(typeof data14.provider !== "string"){ -const err101 = {instancePath:instancePath+"/agent/provider",schemaPath:"#/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data14.effort !== undefined){ -if(typeof data14.effort !== "string"){ -const err102 = {instancePath:instancePath+"/agent/effort",schemaPath:"#/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data14.cwd !== undefined){ -if(typeof data14.cwd !== "string"){ -const err103 = {instancePath:instancePath+"/agent/cwd",schemaPath:"#/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data14.report !== undefined){ -if(typeof data14.report !== "string"){ -const err104 = {instancePath:instancePath+"/agent/report",schemaPath:"#/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data14.status !== undefined){ -if(typeof data14.status !== "string"){ -const err105 = {instancePath:instancePath+"/agent/status",schemaPath:"#/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data14.pending_mail !== undefined){ -let data45 = data14.pending_mail; -if(!((typeof data45 == "number") && (!(data45 % 1) && !isNaN(data45)))){ -const err106 = {instancePath:instancePath+"/agent/pending_mail",schemaPath:"#/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data14.lifecycle_phase !== undefined){ -if(typeof data14.lifecycle_phase !== "string"){ -const err107 = {instancePath:instancePath+"/agent/lifecycle_phase",schemaPath:"#/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data14.blocking_reason !== undefined){ -if(typeof data14.blocking_reason !== "string"){ -const err108 = {instancePath:instancePath+"/agent/blocking_reason",schemaPath:"#/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data14.terminal_cause !== undefined){ -if(typeof data14.terminal_cause !== "string"){ -const err109 = {instancePath:instancePath+"/agent/terminal_cause",schemaPath:"#/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data14.allowed_controls !== undefined){ -let data49 = data14.allowed_controls; -if((data49 !== null) && (!(Array.isArray(data49)))){ -const err110 = {instancePath:instancePath+"/agent/allowed_controls",schemaPath:"#/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema16.properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -if(Array.isArray(data49)){ -const len0 = data49.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data49[i0] !== "string"){ -const err111 = {instancePath:instancePath+"/agent/allowed_controls/" + i0,schemaPath:"#/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -} -} -} -else { -const err112 = {instancePath:instancePath+"/agent",schemaPath:"#/properties/agent/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data.page !== undefined){ -let data51 = data.page; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.history_revision === undefined){ -const err113 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(data51.through_seq === undefined){ -const err114 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data51.next_seq === undefined){ -const err115 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -if(data51.has_more === undefined){ -const err116 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -if(data51.messages === undefined){ -const err117 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(data51.history_revision !== undefined){ -let data52 = data51.history_revision; -if(typeof data52 === "string"){ -if(!pattern0.test(data52)){ -const err118 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(!(formats0.validate(data52))){ -const err119 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -else { -const err120 = {instancePath:instancePath+"/page/history_revision",schemaPath:"#/properties/page/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -if(data51.through_seq !== undefined){ -let data53 = data51.through_seq; -if(!((typeof data53 == "number") && (!(data53 % 1) && !isNaN(data53)))){ -const err121 = {instancePath:instancePath+"/page/through_seq",schemaPath:"#/properties/page/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -if(data51.next_seq !== undefined){ -let data54 = data51.next_seq; -if(!((typeof data54 == "number") && (!(data54 % 1) && !isNaN(data54)))){ -const err122 = {instancePath:instancePath+"/page/next_seq",schemaPath:"#/properties/page/properties/next_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data51.has_more !== undefined){ -if(typeof data51.has_more !== "boolean"){ -const err123 = {instancePath:instancePath+"/page/has_more",schemaPath:"#/properties/page/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data51.messages !== undefined){ -let data56 = data51.messages; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err124 = {instancePath:instancePath+"/page/messages",schemaPath:"#/properties/page/properties/messages/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -if(Array.isArray(data56)){ -const len1 = data56.length; -for(let i1=0; i1<len1; i1++){ -let data57 = data56[i1]; -if(data57 && typeof data57 == "object" && !Array.isArray(data57)){ -if(data57.seq === undefined){ -const err125 = {instancePath:instancePath+"/page/messages/" + i1,schemaPath:"#/properties/page/properties/messages/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -if(data57.presentation !== undefined){ -let data58 = data57.presentation; -if((data58 !== null) && (!(data58 && typeof data58 == "object" && !Array.isArray(data58)))){ -const err126 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(data58 && typeof data58 == "object" && !Array.isArray(data58)){ -if(data58.version === undefined){ -const err127 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -if(data58.design_context !== undefined){ -let data59 = data58.design_context; -if((data59 !== null) && (!(data59 && typeof data59 == "object" && !Array.isArray(data59)))){ -const err128 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -if(data59 && typeof data59 == "object" && !Array.isArray(data59)){ -if(data59.context_attachment_id === undefined){ -const err129 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -if(data59.elements === undefined){ -const err130 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -if(data59.element_count === undefined){ -const err131 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -if(data59.context_part_index === undefined){ -const err132 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -if(data59.context_attachment_id !== undefined){ -if(typeof data59.context_attachment_id !== "string"){ -const err133 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data59.screenshot_attachment_id !== undefined){ -if(typeof data59.screenshot_attachment_id !== "string"){ -const err134 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data59.elements !== undefined){ -let data62 = data59.elements; -if((data62 !== null) && (!(Array.isArray(data62)))){ -const err135 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -if(Array.isArray(data62)){ -const len2 = data62.length; -for(let i2=0; i2<len2; i2++){ -let data63 = data62[i2]; -if(data63 && typeof data63 == "object" && !Array.isArray(data63)){ -if(data63.label === undefined){ -const err136 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -if(data63.label !== undefined){ -if(typeof data63.label !== "string"){ -const err137 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2+"/label",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -if(data63.selector !== undefined){ -if(typeof data63.selector !== "string"){ -const err138 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2+"/selector",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -else { -const err139 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/elements/" + i2,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -} -} -if(data59.element_count !== undefined){ -let data66 = data59.element_count; -if(!((typeof data66 == "number") && (!(data66 % 1) && !isNaN(data66)))){ -const err140 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/element_count",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -if(data59.page_url !== undefined){ -if(typeof data59.page_url !== "string"){ -const err141 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/page_url",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -if(data59.page_title !== undefined){ -if(typeof data59.page_title !== "string"){ -const err142 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/page_title",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data59.context_part_index !== undefined){ -let data69 = data59.context_part_index; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err143 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/context_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data59.screenshot_part_index !== undefined){ -let data70 = data59.screenshot_part_index; -if((data70 !== null) && (!((typeof data70 == "number") && (!(data70 % 1) && !isNaN(data70))))){ -const err144 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -} -} -if(data58.version !== undefined){ -let data71 = data58.version; -if(!((typeof data71 == "number") && (!(data71 % 1) && !isNaN(data71)))){ -const err145 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/version",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -if(data58.turn_id !== undefined){ -if(typeof data58.turn_id !== "string"){ -const err146 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/turn_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -if(data58.parts !== undefined){ -let data73 = data58.parts; -if((data73 !== null) && (!(Array.isArray(data73)))){ -const err147 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -if(Array.isArray(data73)){ -const len3 = data73.length; -for(let i3=0; i3<len3; i3++){ -let data74 = data73[i3]; -if(data74 && typeof data74 == "object" && !Array.isArray(data74)){ -if(data74.id === undefined){ -const err148 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -if(data74.kind === undefined){ -const err149 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -if(data74.id !== undefined){ -if(typeof data74.id !== "string"){ -const err150 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -if(data74.kind !== undefined){ -if(typeof data74.kind !== "string"){ -const err151 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/kind",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data74.start !== undefined){ -let data77 = data74.start; -if(!((typeof data77 == "number") && (!(data77 % 1) && !isNaN(data77)))){ -const err152 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/start",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data74.end !== undefined){ -let data78 = data74.end; -if(!((typeof data78 == "number") && (!(data78 % 1) && !isNaN(data78)))){ -const err153 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/end",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -if(data74.text !== undefined){ -if(typeof data74.text !== "string"){ -const err154 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -} -if(data74.tool_name !== undefined){ -if(typeof data74.tool_name !== "string"){ -const err155 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/tool_name",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -} -if(data74.status !== undefined){ -if(typeof data74.status !== "string"){ -const err156 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -} -if(data74.call_id !== undefined){ -if(typeof data74.call_id !== "string"){ -const err157 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -} -if(data74.hosts !== undefined){ -let data83 = data74.hosts; -if((data83 !== null) && (!(Array.isArray(data83)))){ -const err158 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -if(Array.isArray(data83)){ -const len4 = data83.length; -for(let i4=0; i4<len4; i4++){ -let data84 = data83[i4]; -if(data84 && typeof data84 == "object" && !Array.isArray(data84)){ -if(data84.invocation_id === undefined){ -const err159 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -if(data84.name === undefined){ -const err160 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -if(data84.status === undefined){ -const err161 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -if(data84.invocation_id !== undefined){ -if(typeof data84.invocation_id !== "string"){ -const err162 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/invocation_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -} -if(data84.name !== undefined){ -if(typeof data84.name !== "string"){ -const err163 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/name",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -} -if(data84.summary !== undefined){ -if(typeof data84.summary !== "string"){ -const err164 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/summary",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data84.status !== undefined){ -if(typeof data84.status !== "string"){ -const err165 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -if(data84.duration !== undefined){ -if(typeof data84.duration !== "string"){ -const err166 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/duration",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -if(data84.error !== undefined){ -if(typeof data84.error !== "string"){ -const err167 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/error",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -if(data84.display !== undefined){ -let data91 = data84.display; -if((data91 !== null) && (!(data91 && typeof data91 == "object" && !Array.isArray(data91)))){ -const err168 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -if(data91 && typeof data91 == "object" && !Array.isArray(data91)){ -if(data91.target !== undefined){ -if(typeof data91.target !== "string"){ -const err169 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/target",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -} -if(data91.command !== undefined){ -if(typeof data91.command !== "string"){ -const err170 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/command",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -} -if(data91.query !== undefined){ -if(typeof data91.query !== "string"){ -const err171 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/query",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -} -if(data91.child_id !== undefined){ -if(typeof data91.child_id !== "string"){ -const err172 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/child_id",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -} -if(data91.label !== undefined){ -if(typeof data91.label !== "string"){ -const err173 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4+"/display/label",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -} -} -} -else { -const err174 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/hosts/" + i4,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -} -} -} -if(data74.omitted !== undefined){ -let data97 = data74.omitted; -if(!((typeof data97 == "number") && (!(data97 % 1) && !isNaN(data97)))){ -const err175 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3+"/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -} -} -else { -const err176 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/parts/" + i3,schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -} -} -} -if(data58.omitted !== undefined){ -let data98 = data58.omitted; -if(!((typeof data98 == "number") && (!(data98 % 1) && !isNaN(data98)))){ -const err177 = {instancePath:instancePath+"/page/messages/" + i1+"/presentation/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -} -} -if(data57.role !== undefined){ -if(typeof data57.role !== "string"){ -const err178 = {instancePath:instancePath+"/page/messages/" + i1+"/role",schemaPath:"#/properties/page/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -if(data57.authored !== undefined){ -if(typeof data57.authored !== "boolean"){ -const err179 = {instancePath:instancePath+"/page/messages/" + i1+"/authored",schemaPath:"#/properties/page/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -if(data57.sent_at !== undefined){ -let data101 = data57.sent_at; -if((data101 !== null) && (typeof data101 !== "string")){ -const err180 = {instancePath:instancePath+"/page/messages/" + i1+"/sent_at",schemaPath:"#/properties/page/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -} -if(data57.seq !== undefined){ -let data102 = data57.seq; -if(!((typeof data102 == "number") && (!(data102 % 1) && !isNaN(data102)))){ -const err181 = {instancePath:instancePath+"/page/messages/" + i1+"/seq",schemaPath:"#/properties/page/properties/messages/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -} -if(data57.message !== undefined){ -let data103 = data57.message; -if((data103 !== null) && (!(data103 && typeof data103 == "object" && !Array.isArray(data103)))){ -const err182 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.role === undefined){ -const err183 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -if(data103.content === undefined){ -const err184 = {instancePath:instancePath+"/page/messages/" + i1+"/message",schemaPath:"#/properties/page/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -if(data103.presentation !== undefined){ -let data104 = data103.presentation; -if((data104 !== null) && (!(data104 && typeof data104 == "object" && !Array.isArray(data104)))){ -const err185 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -if(data104 && typeof data104 == "object" && !Array.isArray(data104)){ -if(data104.version === undefined){ -const err186 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -if(data104.design_context !== undefined){ -let data105 = data104.design_context; -if((data105 !== null) && (!(data105 && typeof data105 == "object" && !Array.isArray(data105)))){ -const err187 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -if(data105 && typeof data105 == "object" && !Array.isArray(data105)){ -if(data105.context_attachment_id === undefined){ -const err188 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -if(data105.elements === undefined){ -const err189 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -if(data105.element_count === undefined){ -const err190 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -if(data105.context_part_index === undefined){ -const err191 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -if(data105.context_attachment_id !== undefined){ -if(typeof data105.context_attachment_id !== "string"){ -const err192 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/context_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -} -if(data105.screenshot_attachment_id !== undefined){ -if(typeof data105.screenshot_attachment_id !== "string"){ -const err193 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -} -if(data105.elements !== undefined){ -let data108 = data105.elements; -if((data108 !== null) && (!(Array.isArray(data108)))){ -const err194 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -if(Array.isArray(data108)){ -const len5 = data108.length; -for(let i5=0; i5<len5; i5++){ -let data109 = data108[i5]; -if(data109 && typeof data109 == "object" && !Array.isArray(data109)){ -if(data109.label === undefined){ -const err195 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(data109.label !== undefined){ -if(typeof data109.label !== "string"){ -const err196 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5+"/label",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -} -if(data109.selector !== undefined){ -if(typeof data109.selector !== "string"){ -const err197 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5+"/selector",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -} -} -else { -const err198 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/elements/" + i5,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -} -} -} -if(data105.element_count !== undefined){ -let data112 = data105.element_count; -if(!((typeof data112 == "number") && (!(data112 % 1) && !isNaN(data112)))){ -const err199 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/element_count",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -} -if(data105.page_url !== undefined){ -if(typeof data105.page_url !== "string"){ -const err200 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/page_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -} -if(data105.page_title !== undefined){ -if(typeof data105.page_title !== "string"){ -const err201 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/page_title",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -} -if(data105.context_part_index !== undefined){ -let data115 = data105.context_part_index; -if(!((typeof data115 == "number") && (!(data115 % 1) && !isNaN(data115)))){ -const err202 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/context_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -} -if(data105.screenshot_part_index !== undefined){ -let data116 = data105.screenshot_part_index; -if((data116 !== null) && (!((typeof data116 == "number") && (!(data116 % 1) && !isNaN(data116))))){ -const err203 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -} -} -} -if(data104.version !== undefined){ -let data117 = data104.version; -if(!((typeof data117 == "number") && (!(data117 % 1) && !isNaN(data117)))){ -const err204 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/version",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -} -if(data104.turn_id !== undefined){ -if(typeof data104.turn_id !== "string"){ -const err205 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/turn_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -} -if(data104.parts !== undefined){ -let data119 = data104.parts; -if((data119 !== null) && (!(Array.isArray(data119)))){ -const err206 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -if(Array.isArray(data119)){ -const len6 = data119.length; -for(let i6=0; i6<len6; i6++){ -let data120 = data119[i6]; -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.id === undefined){ -const err207 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -if(data120.kind === undefined){ -const err208 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -if(data120.id !== undefined){ -if(typeof data120.id !== "string"){ -const err209 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -} -if(data120.kind !== undefined){ -if(typeof data120.kind !== "string"){ -const err210 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/kind",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -} -if(data120.start !== undefined){ -let data123 = data120.start; -if(!((typeof data123 == "number") && (!(data123 % 1) && !isNaN(data123)))){ -const err211 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/start",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -} -if(data120.end !== undefined){ -let data124 = data120.end; -if(!((typeof data124 == "number") && (!(data124 % 1) && !isNaN(data124)))){ -const err212 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/end",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -} -if(data120.text !== undefined){ -if(typeof data120.text !== "string"){ -const err213 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -} -if(data120.tool_name !== undefined){ -if(typeof data120.tool_name !== "string"){ -const err214 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/tool_name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -} -if(data120.status !== undefined){ -if(typeof data120.status !== "string"){ -const err215 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -} -if(data120.call_id !== undefined){ -if(typeof data120.call_id !== "string"){ -const err216 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -} -if(data120.hosts !== undefined){ -let data129 = data120.hosts; -if((data129 !== null) && (!(Array.isArray(data129)))){ -const err217 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -if(Array.isArray(data129)){ -const len7 = data129.length; -for(let i7=0; i7<len7; i7++){ -let data130 = data129[i7]; -if(data130 && typeof data130 == "object" && !Array.isArray(data130)){ -if(data130.invocation_id === undefined){ -const err218 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -if(data130.name === undefined){ -const err219 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -if(data130.status === undefined){ -const err220 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -if(data130.invocation_id !== undefined){ -if(typeof data130.invocation_id !== "string"){ -const err221 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/invocation_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -} -if(data130.name !== undefined){ -if(typeof data130.name !== "string"){ -const err222 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -} -if(data130.summary !== undefined){ -if(typeof data130.summary !== "string"){ -const err223 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/summary",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -} -if(data130.status !== undefined){ -if(typeof data130.status !== "string"){ -const err224 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/status",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -} -if(data130.duration !== undefined){ -if(typeof data130.duration !== "string"){ -const err225 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/duration",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -} -if(data130.error !== undefined){ -if(typeof data130.error !== "string"){ -const err226 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/error",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -} -if(data130.display !== undefined){ -let data137 = data130.display; -if((data137 !== null) && (!(data137 && typeof data137 == "object" && !Array.isArray(data137)))){ -const err227 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -if(data137 && typeof data137 == "object" && !Array.isArray(data137)){ -if(data137.target !== undefined){ -if(typeof data137.target !== "string"){ -const err228 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/target",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -} -if(data137.command !== undefined){ -if(typeof data137.command !== "string"){ -const err229 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/command",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -} -if(data137.query !== undefined){ -if(typeof data137.query !== "string"){ -const err230 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/query",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -} -if(data137.child_id !== undefined){ -if(typeof data137.child_id !== "string"){ -const err231 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/child_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -} -if(data137.label !== undefined){ -if(typeof data137.label !== "string"){ -const err232 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7+"/display/label",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -} -} -} -} -else { -const err233 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/hosts/" + i7,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -} -} -} -if(data120.omitted !== undefined){ -let data143 = data120.omitted; -if(!((typeof data143 == "number") && (!(data143 % 1) && !isNaN(data143)))){ -const err234 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6+"/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -} -} -else { -const err235 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/parts/" + i6,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -} -} -} -if(data104.omitted !== undefined){ -let data144 = data104.omitted; -if(!((typeof data144 == "number") && (!(data144 % 1) && !isNaN(data144)))){ -const err236 = {instancePath:instancePath+"/page/messages/" + i1+"/message/presentation/omitted",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -} -} -} -if(data103.role !== undefined){ -if(typeof data103.role !== "string"){ -const err237 = {instancePath:instancePath+"/page/messages/" + i1+"/message/role",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -} -if(data103.content !== undefined){ -let data146 = data103.content; -const _errs314 = errors; -let valid36 = false; -const _errs315 = errors; -if(typeof data146 !== "string"){ -const err238 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -var _valid0 = _errs315 === errors; -valid36 = valid36 || _valid0; -if(!valid36){ -const _errs317 = errors; -if(Array.isArray(data146)){ -const len8 = data146.length; -for(let i8=0; i8<len8; i8++){ -let data147 = data146[i8]; -if(data147 && typeof data147 == "object" && !Array.isArray(data147)){ -if(data147.type === undefined){ -const err239 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -if(data147.type !== undefined){ -if(typeof data147.type !== "string"){ -const err240 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/type",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data147.text !== undefined){ -if(typeof data147.text !== "string"){ -const err241 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/text",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data147.image_url !== undefined){ -let data150 = data147.image_url; -if((data150 !== null) && (!(data150 && typeof data150 == "object" && !Array.isArray(data150)))){ -const err242 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -if(data150 && typeof data150 == "object" && !Array.isArray(data150)){ -if(data150.url === undefined){ -const err243 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -if(data150.url !== undefined){ -if(typeof data150.url !== "string"){ -const err244 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/image_url/url",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -} -} -} -if(data147.w !== undefined){ -let data152 = data147.w; -if(!((typeof data152 == "number") && (!(data152 % 1) && !isNaN(data152)))){ -const err245 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/w",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -} -if(data147.h !== undefined){ -let data153 = data147.h; -if(!((typeof data153 == "number") && (!(data153 % 1) && !isNaN(data153)))){ -const err246 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8+"/h",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -} -} -else { -const err247 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content/" + i8,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -} -} -else { -const err248 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -var _valid0 = _errs317 === errors; -valid36 = valid36 || _valid0; -} -if(!valid36){ -const err249 = {instancePath:instancePath+"/page/messages/" + i1+"/message/content",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -else { -errors = _errs314; -if(vErrors !== null){ -if(_errs314){ -vErrors.length = _errs314; -} -else { -vErrors = null; -} -} -} -} -if(data103.tool_calls !== undefined){ -let data154 = data103.tool_calls; -if((data154 !== null) && (!(Array.isArray(data154)))){ -const err250 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -if(Array.isArray(data154)){ -const len9 = data154.length; -for(let i9=0; i9<len9; i9++){ -let data155 = data154[i9]; -if(data155 && typeof data155 == "object" && !Array.isArray(data155)){ -if(data155.id === undefined){ -const err251 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -if(data155.type === undefined){ -const err252 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -if(data155.function === undefined){ -const err253 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -if(data155.id !== undefined){ -if(typeof data155.id !== "string"){ -const err254 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -} -if(data155.type !== undefined){ -if(typeof data155.type !== "string"){ -const err255 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/type",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -} -if(data155.function !== undefined){ -let data158 = data155.function; -if(data158 && typeof data158 == "object" && !Array.isArray(data158)){ -if(data158.name === undefined){ -const err256 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -if(data158.arguments === undefined){ -const err257 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -if(data158.name !== undefined){ -if(typeof data158.name !== "string"){ -const err258 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -} -if(data158.arguments !== undefined){ -if(typeof data158.arguments !== "string"){ -const err259 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function/arguments",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -} -} -else { -const err260 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/function",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -} -if(data155.duration_ms !== undefined){ -let data161 = data155.duration_ms; -if(!((typeof data161 == "number") && (!(data161 % 1) && !isNaN(data161)))){ -const err261 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/duration_ms",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -} -if(data155.exit_code !== undefined){ -let data162 = data155.exit_code; -if(!((typeof data162 == "number") && (!(data162 % 1) && !isNaN(data162)))){ -const err262 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9+"/exit_code",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -} -} -else { -const err263 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_calls/" + i9,schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -} -} -} -if(data103.tool_call_id !== undefined){ -if(typeof data103.tool_call_id !== "string"){ -const err264 = {instancePath:instancePath+"/page/messages/" + i1+"/message/tool_call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -} -if(data103.name !== undefined){ -if(typeof data103.name !== "string"){ -const err265 = {instancePath:instancePath+"/page/messages/" + i1+"/message/name",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -} -if(data103.authored !== undefined){ -if(typeof data103.authored !== "boolean"){ -const err266 = {instancePath:instancePath+"/page/messages/" + i1+"/message/authored",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -} -if(data103.sent_at !== undefined){ -let data166 = data103.sent_at; -if((data166 !== null) && (typeof data166 !== "string")){ -const err267 = {instancePath:instancePath+"/page/messages/" + i1+"/message/sent_at",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/sent_at/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -} -if(data103.usage !== undefined){ -let data167 = data103.usage; -if((data167 !== null) && (!(data167 && typeof data167 == "object" && !Array.isArray(data167)))){ -const err268 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -if(data167 && typeof data167 == "object" && !Array.isArray(data167)){ -if(data167.prompt_tokens === undefined){ -const err269 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -if(data167.completion_tokens === undefined){ -const err270 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -if(data167.reported !== undefined){ -if(typeof data167.reported !== "boolean"){ -const err271 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/reported",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -} -if(data167.cost !== undefined){ -let data169 = data167.cost; -if((data169 !== null) && (!(typeof data169 == "number"))){ -const err272 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/cost",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/cost/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -} -if(data167.prompt_tokens !== undefined){ -let data170 = data167.prompt_tokens; -if(!((typeof data170 == "number") && (!(data170 % 1) && !isNaN(data170)))){ -const err273 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -} -if(data167.completion_tokens !== undefined){ -let data171 = data167.completion_tokens; -if(!((typeof data171 == "number") && (!(data171 % 1) && !isNaN(data171)))){ -const err274 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -} -if(data167.prompt_tokens_details !== undefined){ -let data172 = data167.prompt_tokens_details; -if((data172 !== null) && (!(data172 && typeof data172 == "object" && !Array.isArray(data172)))){ -const err275 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -if(data172 && typeof data172 == "object" && !Array.isArray(data172)){ -if(data172.cached_tokens === undefined){ -const err276 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -if(data172.cached_tokens !== undefined){ -let data173 = data172.cached_tokens; -if(!((typeof data173 == "number") && (!(data173 % 1) && !isNaN(data173)))){ -const err277 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -} -} -} -if(data167.completion_tokens_details !== undefined){ -let data174 = data167.completion_tokens_details; -if((data174 !== null) && (!(data174 && typeof data174 == "object" && !Array.isArray(data174)))){ -const err278 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.message.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -if(data174 && typeof data174 == "object" && !Array.isArray(data174)){ -if(data174.reasoning_tokens === undefined){ -const err279 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -if(data174.reasoning_tokens !== undefined){ -let data175 = data174.reasoning_tokens; -if(!((typeof data175 == "number") && (!(data175 % 1) && !isNaN(data175)))){ -const err280 = {instancePath:instancePath+"/page/messages/" + i1+"/message/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -} -} -} -} -} -if(data103.model !== undefined){ -if(typeof data103.model !== "string"){ -const err281 = {instancePath:instancePath+"/page/messages/" + i1+"/message/model",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -} -if(data103.rewound_from !== undefined){ -if(typeof data103.rewound_from !== "string"){ -const err282 = {instancePath:instancePath+"/page/messages/" + i1+"/message/rewound_from",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -} -if(data103.call_id !== undefined){ -if(typeof data103.call_id !== "string"){ -const err283 = {instancePath:instancePath+"/page/messages/" + i1+"/message/call_id",schemaPath:"#/properties/page/properties/messages/items/properties/message/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -} -} -} -if(data57.body !== undefined){ -let data179 = data57.body; -if((data179 !== null) && (!(data179 && typeof data179 == "object" && !Array.isArray(data179)))){ -const err284 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -if(data179 && typeof data179 == "object" && !Array.isArray(data179)){ -if(data179.reference_id === undefined){ -const err285 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -if(data179.digest === undefined){ -const err286 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -if(data179.size === undefined){ -const err287 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -if(data179.media_type === undefined){ -const err288 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -if(data179.source === undefined){ -const err289 = {instancePath:instancePath+"/page/messages/" + i1+"/body",schemaPath:"#/properties/page/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -if(data179.text !== undefined){ -let data180 = data179.text; -if((data180 !== null) && (typeof data180 !== "string")){ -const err290 = {instancePath:instancePath+"/page/messages/" + i1+"/body/text",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/text/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -} -if(data179.binary !== undefined){ -let data181 = data179.binary; -if((typeof data181 !== "string") && (data181 !== null)){ -const err291 = {instancePath:instancePath+"/page/messages/" + i1+"/body/binary",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema16.properties.page.properties.messages.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data179.reference_id !== undefined){ -if(typeof data179.reference_id !== "string"){ -const err292 = {instancePath:instancePath+"/page/messages/" + i1+"/body/reference_id",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -} -if(data179.digest !== undefined){ -if(typeof data179.digest !== "string"){ -const err293 = {instancePath:instancePath+"/page/messages/" + i1+"/body/digest",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -} -if(data179.size !== undefined){ -let data184 = data179.size; -if(typeof data184 === "string"){ -if(!pattern0.test(data184)){ -const err294 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -if(!(formats0.validate(data184))){ -const err295 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -} -else { -const err296 = {instancePath:instancePath+"/page/messages/" + i1+"/body/size",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -} -if(data179.media_type !== undefined){ -if(typeof data179.media_type !== "string"){ -const err297 = {instancePath:instancePath+"/page/messages/" + i1+"/body/media_type",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -} -if(data179.source !== undefined){ -if(typeof data179.source !== "string"){ -const err298 = {instancePath:instancePath+"/page/messages/" + i1+"/body/source",schemaPath:"#/properties/page/properties/messages/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -} -} -} -} -else { -const err299 = {instancePath:instancePath+"/page/messages/" + i1,schemaPath:"#/properties/page/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -} -} -} -} -else { -const err300 = {instancePath:instancePath+"/page",schemaPath:"#/properties/page/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -} -if(data.presentation !== undefined){ -let data187 = data.presentation; -if((data187 !== null) && (!(Array.isArray(data187)))){ -const err301 = {instancePath:instancePath+"/presentation",schemaPath:"#/properties/presentation/type",keyword:"type",params:{type: schema16.properties.presentation.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -if(Array.isArray(data187)){ -const len10 = data187.length; -for(let i10=0; i10<len10; i10++){ -let data188 = data187[i10]; -if(data188 && typeof data188 == "object" && !Array.isArray(data188)){ -if(data188.seq === undefined){ -const err302 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -if(data188.kind === undefined){ -const err303 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -if(data188.payload === undefined){ -const err304 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -if(data188.seq !== undefined){ -let data189 = data188.seq; -if(typeof data189 === "string"){ -if(!pattern0.test(data189)){ -const err305 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -if(!(formats0.validate(data189))){ -const err306 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -} -else { -const err307 = {instancePath:instancePath+"/presentation/" + i10+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -} -if(data188.kind !== undefined){ -if(typeof data188.kind !== "string"){ -const err308 = {instancePath:instancePath+"/presentation/" + i10+"/kind",schemaPath:"#/properties/presentation/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -} -} -else { -const err309 = {instancePath:instancePath+"/presentation/" + i10,schemaPath:"#/properties/presentation/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -} -} -} -if(data.inbox !== undefined){ -let data191 = data.inbox; -if((data191 !== null) && (!(Array.isArray(data191)))){ -const err310 = {instancePath:instancePath+"/inbox",schemaPath:"#/properties/inbox/type",keyword:"type",params:{type: schema16.properties.inbox.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -if(Array.isArray(data191)){ -const len11 = data191.length; -for(let i11=0; i11<len11; i11++){ -let data192 = data191[i11]; -if(data192 && typeof data192 == "object" && !Array.isArray(data192)){ -if(data192.root_id === undefined){ -const err311 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -if(data192.agent_id === undefined){ -const err312 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -if(data192.seq === undefined){ -const err313 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -if(data192.kind === undefined){ -const err314 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -if(data192.status === undefined){ -const err315 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -if(data192.payload === undefined){ -const err316 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -if(data192.delivery_seq !== undefined){ -let data193 = data192.delivery_seq; -if(typeof data193 === "string"){ -if(!pattern0.test(data193)){ -const err317 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -if(!(formats0.validate(data193))){ -const err318 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -} -else { -const err319 = {instancePath:instancePath+"/inbox/" + i11+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -} -if(data192.origin !== undefined){ -if(typeof data192.origin !== "string"){ -const err320 = {instancePath:instancePath+"/inbox/" + i11+"/origin",schemaPath:"#/properties/inbox/items/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -} -if(data192.command_client_id !== undefined){ -if(typeof data192.command_client_id !== "string"){ -const err321 = {instancePath:instancePath+"/inbox/" + i11+"/command_client_id",schemaPath:"#/properties/inbox/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -} -if(data192.command_id !== undefined){ -if(typeof data192.command_id !== "string"){ -const err322 = {instancePath:instancePath+"/inbox/" + i11+"/command_id",schemaPath:"#/properties/inbox/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -} -if(data192.steer_turn_id !== undefined){ -if(typeof data192.steer_turn_id !== "string"){ -const err323 = {instancePath:instancePath+"/inbox/" + i11+"/steer_turn_id",schemaPath:"#/properties/inbox/items/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -} -if(data192.preview !== undefined){ -let data198 = data192.preview; -if((data198 !== null) && (!(data198 && typeof data198 == "object" && !Array.isArray(data198)))){ -const err324 = {instancePath:instancePath+"/inbox/" + i11+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -if(data198 && typeof data198 == "object" && !Array.isArray(data198)){ -if(data198.text === undefined){ -const err325 = {instancePath:instancePath+"/inbox/" + i11+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -if(data198.design_context !== undefined){ -let data199 = data198.design_context; -if((data199 !== null) && (!(data199 && typeof data199 == "object" && !Array.isArray(data199)))){ -const err326 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -if(data199 && typeof data199 == "object" && !Array.isArray(data199)){ -if(data199.context_attachment_id === undefined){ -const err327 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -if(data199.elements === undefined){ -const err328 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -if(data199.element_count === undefined){ -const err329 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -if(data199.context_attachment_id !== undefined){ -if(typeof data199.context_attachment_id !== "string"){ -const err330 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/context_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -} -if(data199.screenshot_attachment_id !== undefined){ -if(typeof data199.screenshot_attachment_id !== "string"){ -const err331 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -} -if(data199.elements !== undefined){ -let data202 = data199.elements; -if((data202 !== null) && (!(Array.isArray(data202)))){ -const err332 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -if(Array.isArray(data202)){ -const len12 = data202.length; -for(let i12=0; i12<len12; i12++){ -let data203 = data202[i12]; -if(data203 && typeof data203 == "object" && !Array.isArray(data203)){ -if(data203.label === undefined){ -const err333 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -if(data203.label !== undefined){ -if(typeof data203.label !== "string"){ -const err334 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12+"/label",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -} -if(data203.selector !== undefined){ -if(typeof data203.selector !== "string"){ -const err335 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12+"/selector",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -} -else { -const err336 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/elements/" + i12,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -} -} -} -if(data199.element_count !== undefined){ -let data206 = data199.element_count; -if(!((typeof data206 == "number") && (!(data206 % 1) && !isNaN(data206)))){ -const err337 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/element_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -} -if(data199.page_url !== undefined){ -if(typeof data199.page_url !== "string"){ -const err338 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/page_url",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -} -if(data199.page_title !== undefined){ -if(typeof data199.page_title !== "string"){ -const err339 = {instancePath:instancePath+"/inbox/" + i11+"/preview/design_context/page_title",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -} -} -} -if(data198.text !== undefined){ -if(typeof data198.text !== "string"){ -const err340 = {instancePath:instancePath+"/inbox/" + i11+"/preview/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -} -if(data198.truncated !== undefined){ -if(typeof data198.truncated !== "boolean"){ -const err341 = {instancePath:instancePath+"/inbox/" + i11+"/preview/truncated",schemaPath:"#/properties/inbox/items/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -} -if(data198.attachments !== undefined){ -let data211 = data198.attachments; -if((data211 !== null) && (!(Array.isArray(data211)))){ -const err342 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -if(Array.isArray(data211)){ -const len13 = data211.length; -for(let i13=0; i13<len13; i13++){ -let data212 = data211[i13]; -if(data212 && typeof data212 == "object" && !Array.isArray(data212)){ -if(data212.kind === undefined){ -const err343 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -if(data212.content === undefined){ -const err344 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -if(data212.kind !== undefined){ -if(typeof data212.kind !== "string"){ -const err345 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/kind",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -} -if(data212.name !== undefined){ -if(typeof data212.name !== "string"){ -const err346 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/name",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -} -if(data212.content !== undefined){ -let data215 = data212.content; -if(data215 && typeof data215 == "object" && !Array.isArray(data215)){ -if(data215.reference_id === undefined){ -const err347 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -if(data215.digest === undefined){ -const err348 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -if(data215.size === undefined){ -const err349 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -if(data215.media_type === undefined){ -const err350 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -if(data215.source === undefined){ -const err351 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -if(data215.text !== undefined){ -let data216 = data215.text; -if((data216 !== null) && (typeof data216 !== "string")){ -const err352 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -} -if(data215.binary !== undefined){ -let data217 = data215.binary; -if((typeof data217 !== "string") && (data217 !== null)){ -const err353 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/binary",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -} -if(data215.reference_id !== undefined){ -if(typeof data215.reference_id !== "string"){ -const err354 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/reference_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -} -if(data215.digest !== undefined){ -if(typeof data215.digest !== "string"){ -const err355 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/digest",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -} -if(data215.size !== undefined){ -let data220 = data215.size; -if(typeof data220 === "string"){ -if(!pattern0.test(data220)){ -const err356 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -if(!(formats0.validate(data220))){ -const err357 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -} -else { -const err358 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -} -if(data215.media_type !== undefined){ -if(typeof data215.media_type !== "string"){ -const err359 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/media_type",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -} -if(data215.source !== undefined){ -if(typeof data215.source !== "string"){ -const err360 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content/source",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -} -} -else { -const err361 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -} -} -else { -const err362 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachments/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -} -} -} -if(data198.attachment_count !== undefined){ -let data223 = data198.attachment_count; -if(!((typeof data223 == "number") && (!(data223 % 1) && !isNaN(data223)))){ -const err363 = {instancePath:instancePath+"/inbox/" + i11+"/preview/attachment_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -} -} -} -if(data192.root_id !== undefined){ -if(typeof data192.root_id !== "string"){ -const err364 = {instancePath:instancePath+"/inbox/" + i11+"/root_id",schemaPath:"#/properties/inbox/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -} -if(data192.agent_id !== undefined){ -if(typeof data192.agent_id !== "string"){ -const err365 = {instancePath:instancePath+"/inbox/" + i11+"/agent_id",schemaPath:"#/properties/inbox/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -} -if(data192.seq !== undefined){ -let data226 = data192.seq; -if(typeof data226 === "string"){ -if(!pattern0.test(data226)){ -const err366 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -if(!(formats0.validate(data226))){ -const err367 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -} -else { -const err368 = {instancePath:instancePath+"/inbox/" + i11+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -} -if(data192.kind !== undefined){ -if(typeof data192.kind !== "string"){ -const err369 = {instancePath:instancePath+"/inbox/" + i11+"/kind",schemaPath:"#/properties/inbox/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -} -if(data192.status !== undefined){ -if(typeof data192.status !== "string"){ -const err370 = {instancePath:instancePath+"/inbox/" + i11+"/status",schemaPath:"#/properties/inbox/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -} -if(data192.payload !== undefined){ -let data229 = data192.payload; -if(data229 && typeof data229 == "object" && !Array.isArray(data229)){ -if(data229.reference_id === undefined){ -const err371 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -if(data229.digest === undefined){ -const err372 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -if(data229.size === undefined){ -const err373 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -if(data229.media_type === undefined){ -const err374 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -if(data229.source === undefined){ -const err375 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -if(data229.text !== undefined){ -let data230 = data229.text; -if((data230 !== null) && (typeof data230 !== "string")){ -const err376 = {instancePath:instancePath+"/inbox/" + i11+"/payload/text",schemaPath:"#/properties/inbox/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -} -if(data229.binary !== undefined){ -let data231 = data229.binary; -if((typeof data231 !== "string") && (data231 !== null)){ -const err377 = {instancePath:instancePath+"/inbox/" + i11+"/payload/binary",schemaPath:"#/properties/inbox/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema16.properties.inbox.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -} -if(data229.reference_id !== undefined){ -if(typeof data229.reference_id !== "string"){ -const err378 = {instancePath:instancePath+"/inbox/" + i11+"/payload/reference_id",schemaPath:"#/properties/inbox/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -} -if(data229.digest !== undefined){ -if(typeof data229.digest !== "string"){ -const err379 = {instancePath:instancePath+"/inbox/" + i11+"/payload/digest",schemaPath:"#/properties/inbox/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -} -if(data229.size !== undefined){ -let data234 = data229.size; -if(typeof data234 === "string"){ -if(!pattern0.test(data234)){ -const err380 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -if(!(formats0.validate(data234))){ -const err381 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -} -else { -const err382 = {instancePath:instancePath+"/inbox/" + i11+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -} -if(data229.media_type !== undefined){ -if(typeof data229.media_type !== "string"){ -const err383 = {instancePath:instancePath+"/inbox/" + i11+"/payload/media_type",schemaPath:"#/properties/inbox/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -} -if(data229.source !== undefined){ -if(typeof data229.source !== "string"){ -const err384 = {instancePath:instancePath+"/inbox/" + i11+"/payload/source",schemaPath:"#/properties/inbox/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -} -} -else { -const err385 = {instancePath:instancePath+"/inbox/" + i11+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -} -} -else { -const err386 = {instancePath:instancePath+"/inbox/" + i11,schemaPath:"#/properties/inbox/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -} -} -} -else { -const err387 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -validate15.errors = vErrors; -return errors === 0; -} - -export const ArchiveParams = validate16; -const schema17 = {"type":"object","properties":{"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ArchiveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ArchiveParams","required":["archived"],"additionalProperties":true}; - -function validate16(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ArchiveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.archived === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err1 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate16.errors = vErrors; -return errors === 0; -} - -export const ArchiveResult = validate17; -const schema18 = {"type":"object","properties":{"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ArchiveResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ArchiveResult","required":["archived"],"additionalProperties":true}; - -function validate17(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ArchiveResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.archived === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err1 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate17.errors = vErrors; -return errors === 0; -} - -export const BoundedTranscriptPage = validate18; -const schema19 = {"type":"object","properties":{"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"through_seq":{"type":"integer"},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":true},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true}},"required":["invocation_id","name","status"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":true},"role":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"seq":{"type":"integer"},"message":{"type":["null","object"],"properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":true},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true}},"required":["invocation_id","name","status"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":true},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":true},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":true}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":true},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["seq"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/BoundedTranscriptPage","$schema":"http://json-schema.org/draft-07/schema#","title":"BoundedTranscriptPage","required":["history_revision","through_seq","next_seq","has_more","messages"],"additionalProperties":true}; - -function validate18(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BoundedTranscriptPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.history_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.through_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.next_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.messages === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.history_revision !== undefined){ -let data0 = data.history_revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err5 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err6 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.through_seq !== undefined){ -let data1 = data.through_seq; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err8 = {instancePath:instancePath+"/through_seq",schemaPath:"#/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.next_seq !== undefined){ -let data2 = data.next_seq; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err9 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err10 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.messages !== undefined){ -let data4 = data.messages; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err11 = {instancePath:instancePath+"/messages",schemaPath:"#/properties/messages/type",keyword:"type",params:{type: schema19.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -let data5 = data4[i0]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.seq === undefined){ -const err12 = {instancePath:instancePath+"/messages/" + i0,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data5.presentation !== undefined){ -let data6 = data5.presentation; -if((data6 !== null) && (!(data6 && typeof data6 == "object" && !Array.isArray(data6)))){ -const err13 = {instancePath:instancePath+"/messages/" + i0+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.version === undefined){ -const err14 = {instancePath:instancePath+"/messages/" + i0+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data6.design_context !== undefined){ -let data7 = data6.design_context; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err15 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.context_attachment_id === undefined){ -const err16 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.elements === undefined){ -const err17 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.element_count === undefined){ -const err18 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.context_part_index === undefined){ -const err19 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.context_attachment_id !== undefined){ -if(typeof data7.context_attachment_id !== "string"){ -const err20 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data7.screenshot_attachment_id !== undefined){ -if(typeof data7.screenshot_attachment_id !== "string"){ -const err21 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.elements !== undefined){ -let data10 = data7.elements; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err22 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -let data11 = data10[i1]; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.label === undefined){ -const err23 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data11.label !== undefined){ -if(typeof data11.label !== "string"){ -const err24 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1+"/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data11.selector !== undefined){ -if(typeof data11.selector !== "string"){ -const err25 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1+"/selector",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -else { -const err26 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/elements/" + i1,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -} -if(data7.element_count !== undefined){ -let data14 = data7.element_count; -if(!((typeof data14 == "number") && (!(data14 % 1) && !isNaN(data14)))){ -const err27 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data7.page_url !== undefined){ -if(typeof data7.page_url !== "string"){ -const err28 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data7.page_title !== undefined){ -if(typeof data7.page_title !== "string"){ -const err29 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data7.context_part_index !== undefined){ -let data17 = data7.context_part_index; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err30 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data7.screenshot_part_index !== undefined){ -let data18 = data7.screenshot_part_index; -if((data18 !== null) && (!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18))))){ -const err31 = {instancePath:instancePath+"/messages/" + i0+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -} -if(data6.version !== undefined){ -let data19 = data6.version; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err32 = {instancePath:instancePath+"/messages/" + i0+"/presentation/version",schemaPath:"#/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data6.turn_id !== undefined){ -if(typeof data6.turn_id !== "string"){ -const err33 = {instancePath:instancePath+"/messages/" + i0+"/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data6.parts !== undefined){ -let data21 = data6.parts; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err34 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(Array.isArray(data21)){ -const len2 = data21.length; -for(let i2=0; i2<len2; i2++){ -let data22 = data21[i2]; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.id === undefined){ -const err35 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data22.kind === undefined){ -const err36 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data22.id !== undefined){ -if(typeof data22.id !== "string"){ -const err37 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data22.kind !== undefined){ -if(typeof data22.kind !== "string"){ -const err38 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/kind",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data22.start !== undefined){ -let data25 = data22.start; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err39 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/start",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data22.end !== undefined){ -let data26 = data22.end; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err40 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/end",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data22.text !== undefined){ -if(typeof data22.text !== "string"){ -const err41 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/text",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data22.tool_name !== undefined){ -if(typeof data22.tool_name !== "string"){ -const err42 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/tool_name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data22.status !== undefined){ -if(typeof data22.status !== "string"){ -const err43 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data22.call_id !== undefined){ -if(typeof data22.call_id !== "string"){ -const err44 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/call_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data22.hosts !== undefined){ -let data31 = data22.hosts; -if((data31 !== null) && (!(Array.isArray(data31)))){ -const err45 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(Array.isArray(data31)){ -const len3 = data31.length; -for(let i3=0; i3<len3; i3++){ -let data32 = data31[i3]; -if(data32 && typeof data32 == "object" && !Array.isArray(data32)){ -if(data32.invocation_id === undefined){ -const err46 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data32.name === undefined){ -const err47 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data32.status === undefined){ -const err48 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data32.invocation_id !== undefined){ -if(typeof data32.invocation_id !== "string"){ -const err49 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/invocation_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data32.name !== undefined){ -if(typeof data32.name !== "string"){ -const err50 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data32.summary !== undefined){ -if(typeof data32.summary !== "string"){ -const err51 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/summary",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data32.status !== undefined){ -if(typeof data32.status !== "string"){ -const err52 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data32.duration !== undefined){ -if(typeof data32.duration !== "string"){ -const err53 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/duration",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data32.error !== undefined){ -if(typeof data32.error !== "string"){ -const err54 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/error",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data32.display !== undefined){ -let data39 = data32.display; -if((data39 !== null) && (!(data39 && typeof data39 == "object" && !Array.isArray(data39)))){ -const err55 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data39 && typeof data39 == "object" && !Array.isArray(data39)){ -if(data39.target !== undefined){ -if(typeof data39.target !== "string"){ -const err56 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/target",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data39.command !== undefined){ -if(typeof data39.command !== "string"){ -const err57 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/command",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data39.query !== undefined){ -if(typeof data39.query !== "string"){ -const err58 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/query",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data39.child_id !== undefined){ -if(typeof data39.child_id !== "string"){ -const err59 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/child_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data39.label !== undefined){ -if(typeof data39.label !== "string"){ -const err60 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3+"/display/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -} -} -} -else { -const err61 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/hosts/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -} -} -if(data22.omitted !== undefined){ -let data45 = data22.omitted; -if(!((typeof data45 == "number") && (!(data45 % 1) && !isNaN(data45)))){ -const err62 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2+"/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -} -else { -const err63 = {instancePath:instancePath+"/messages/" + i0+"/presentation/parts/" + i2,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -} -} -if(data6.omitted !== undefined){ -let data46 = data6.omitted; -if(!((typeof data46 == "number") && (!(data46 % 1) && !isNaN(data46)))){ -const err64 = {instancePath:instancePath+"/messages/" + i0+"/presentation/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data5.role !== undefined){ -if(typeof data5.role !== "string"){ -const err65 = {instancePath:instancePath+"/messages/" + i0+"/role",schemaPath:"#/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data5.authored !== undefined){ -if(typeof data5.authored !== "boolean"){ -const err66 = {instancePath:instancePath+"/messages/" + i0+"/authored",schemaPath:"#/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data5.sent_at !== undefined){ -let data49 = data5.sent_at; -if((data49 !== null) && (typeof data49 !== "string")){ -const err67 = {instancePath:instancePath+"/messages/" + i0+"/sent_at",schemaPath:"#/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data5.seq !== undefined){ -let data50 = data5.seq; -if(!((typeof data50 == "number") && (!(data50 % 1) && !isNaN(data50)))){ -const err68 = {instancePath:instancePath+"/messages/" + i0+"/seq",schemaPath:"#/properties/messages/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data5.message !== undefined){ -let data51 = data5.message; -if((data51 !== null) && (!(data51 && typeof data51 == "object" && !Array.isArray(data51)))){ -const err69 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.role === undefined){ -const err70 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data51.content === undefined){ -const err71 = {instancePath:instancePath+"/messages/" + i0+"/message",schemaPath:"#/properties/messages/items/properties/message/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data51.presentation !== undefined){ -let data52 = data51.presentation; -if((data52 !== null) && (!(data52 && typeof data52 == "object" && !Array.isArray(data52)))){ -const err72 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(data52 && typeof data52 == "object" && !Array.isArray(data52)){ -if(data52.version === undefined){ -const err73 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(data52.design_context !== undefined){ -let data53 = data52.design_context; -if((data53 !== null) && (!(data53 && typeof data53 == "object" && !Array.isArray(data53)))){ -const err74 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(data53 && typeof data53 == "object" && !Array.isArray(data53)){ -if(data53.context_attachment_id === undefined){ -const err75 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(data53.elements === undefined){ -const err76 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -if(data53.element_count === undefined){ -const err77 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data53.context_part_index === undefined){ -const err78 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data53.context_attachment_id !== undefined){ -if(typeof data53.context_attachment_id !== "string"){ -const err79 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data53.screenshot_attachment_id !== undefined){ -if(typeof data53.screenshot_attachment_id !== "string"){ -const err80 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data53.elements !== undefined){ -let data56 = data53.elements; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err81 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(Array.isArray(data56)){ -const len4 = data56.length; -for(let i4=0; i4<len4; i4++){ -let data57 = data56[i4]; -if(data57 && typeof data57 == "object" && !Array.isArray(data57)){ -if(data57.label === undefined){ -const err82 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data57.label !== undefined){ -if(typeof data57.label !== "string"){ -const err83 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4+"/label",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data57.selector !== undefined){ -if(typeof data57.selector !== "string"){ -const err84 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4+"/selector",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -} -else { -const err85 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/elements/" + i4,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -} -} -if(data53.element_count !== undefined){ -let data60 = data53.element_count; -if(!((typeof data60 == "number") && (!(data60 % 1) && !isNaN(data60)))){ -const err86 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data53.page_url !== undefined){ -if(typeof data53.page_url !== "string"){ -const err87 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data53.page_title !== undefined){ -if(typeof data53.page_title !== "string"){ -const err88 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data53.context_part_index !== undefined){ -let data63 = data53.context_part_index; -if(!((typeof data63 == "number") && (!(data63 % 1) && !isNaN(data63)))){ -const err89 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data53.screenshot_part_index !== undefined){ -let data64 = data53.screenshot_part_index; -if((data64 !== null) && (!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64))))){ -const err90 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -} -if(data52.version !== undefined){ -let data65 = data52.version; -if(!((typeof data65 == "number") && (!(data65 % 1) && !isNaN(data65)))){ -const err91 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/version",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data52.turn_id !== undefined){ -if(typeof data52.turn_id !== "string"){ -const err92 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data52.parts !== undefined){ -let data67 = data52.parts; -if((data67 !== null) && (!(Array.isArray(data67)))){ -const err93 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(Array.isArray(data67)){ -const len5 = data67.length; -for(let i5=0; i5<len5; i5++){ -let data68 = data67[i5]; -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -if(data68.id === undefined){ -const err94 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(data68.kind === undefined){ -const err95 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -if(data68.id !== undefined){ -if(typeof data68.id !== "string"){ -const err96 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data68.kind !== undefined){ -if(typeof data68.kind !== "string"){ -const err97 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/kind",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data68.start !== undefined){ -let data71 = data68.start; -if(!((typeof data71 == "number") && (!(data71 % 1) && !isNaN(data71)))){ -const err98 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/start",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data68.end !== undefined){ -let data72 = data68.end; -if(!((typeof data72 == "number") && (!(data72 % 1) && !isNaN(data72)))){ -const err99 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/end",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data68.text !== undefined){ -if(typeof data68.text !== "string"){ -const err100 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/text",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data68.tool_name !== undefined){ -if(typeof data68.tool_name !== "string"){ -const err101 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/tool_name",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -if(data68.status !== undefined){ -if(typeof data68.status !== "string"){ -const err102 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/status",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data68.call_id !== undefined){ -if(typeof data68.call_id !== "string"){ -const err103 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/call_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data68.hosts !== undefined){ -let data77 = data68.hosts; -if((data77 !== null) && (!(Array.isArray(data77)))){ -const err104 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -if(Array.isArray(data77)){ -const len6 = data77.length; -for(let i6=0; i6<len6; i6++){ -let data78 = data77[i6]; -if(data78 && typeof data78 == "object" && !Array.isArray(data78)){ -if(data78.invocation_id === undefined){ -const err105 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(data78.name === undefined){ -const err106 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(data78.status === undefined){ -const err107 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -if(data78.invocation_id !== undefined){ -if(typeof data78.invocation_id !== "string"){ -const err108 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/invocation_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data78.name !== undefined){ -if(typeof data78.name !== "string"){ -const err109 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/name",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data78.summary !== undefined){ -if(typeof data78.summary !== "string"){ -const err110 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/summary",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data78.status !== undefined){ -if(typeof data78.status !== "string"){ -const err111 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/status",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data78.duration !== undefined){ -if(typeof data78.duration !== "string"){ -const err112 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/duration",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data78.error !== undefined){ -if(typeof data78.error !== "string"){ -const err113 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/error",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -if(data78.display !== undefined){ -let data85 = data78.display; -if((data85 !== null) && (!(data85 && typeof data85 == "object" && !Array.isArray(data85)))){ -const err114 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data85 && typeof data85 == "object" && !Array.isArray(data85)){ -if(data85.target !== undefined){ -if(typeof data85.target !== "string"){ -const err115 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/target",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data85.command !== undefined){ -if(typeof data85.command !== "string"){ -const err116 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/command",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data85.query !== undefined){ -if(typeof data85.query !== "string"){ -const err117 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/query",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -if(data85.child_id !== undefined){ -if(typeof data85.child_id !== "string"){ -const err118 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/child_id",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -if(data85.label !== undefined){ -if(typeof data85.label !== "string"){ -const err119 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6+"/display/label",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -} -} -} -else { -const err120 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/hosts/" + i6,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -} -} -if(data68.omitted !== undefined){ -let data91 = data68.omitted; -if(!((typeof data91 == "number") && (!(data91 % 1) && !isNaN(data91)))){ -const err121 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5+"/omitted",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -} -else { -const err122 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/parts/" + i5,schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -} -} -if(data52.omitted !== undefined){ -let data92 = data52.omitted; -if(!((typeof data92 == "number") && (!(data92 % 1) && !isNaN(data92)))){ -const err123 = {instancePath:instancePath+"/messages/" + i0+"/message/presentation/omitted",schemaPath:"#/properties/messages/items/properties/message/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -} -} -if(data51.role !== undefined){ -if(typeof data51.role !== "string"){ -const err124 = {instancePath:instancePath+"/messages/" + i0+"/message/role",schemaPath:"#/properties/messages/items/properties/message/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data51.content !== undefined){ -let data94 = data51.content; -const _errs205 = errors; -let valid29 = false; -const _errs206 = errors; -if(typeof data94 !== "string"){ -const err125 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -var _valid0 = _errs206 === errors; -valid29 = valid29 || _valid0; -if(!valid29){ -const _errs208 = errors; -if(Array.isArray(data94)){ -const len7 = data94.length; -for(let i7=0; i7<len7; i7++){ -let data95 = data94[i7]; -if(data95 && typeof data95 == "object" && !Array.isArray(data95)){ -if(data95.type === undefined){ -const err126 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7,schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(data95.type !== undefined){ -if(typeof data95.type !== "string"){ -const err127 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/type",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data95.text !== undefined){ -if(typeof data95.text !== "string"){ -const err128 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/text",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data95.image_url !== undefined){ -let data98 = data95.image_url; -if((data98 !== null) && (!(data98 && typeof data98 == "object" && !Array.isArray(data98)))){ -const err129 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -if(data98 && typeof data98 == "object" && !Array.isArray(data98)){ -if(data98.url === undefined){ -const err130 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -if(data98.url !== undefined){ -if(typeof data98.url !== "string"){ -const err131 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/image_url/url",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -} -} -if(data95.w !== undefined){ -let data100 = data95.w; -if(!((typeof data100 == "number") && (!(data100 % 1) && !isNaN(data100)))){ -const err132 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/w",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -if(data95.h !== undefined){ -let data101 = data95.h; -if(!((typeof data101 == "number") && (!(data101 % 1) && !isNaN(data101)))){ -const err133 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7+"/h",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -} -else { -const err134 = {instancePath:instancePath+"/messages/" + i0+"/message/content/" + i7,schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -} -else { -const err135 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -var _valid0 = _errs208 === errors; -valid29 = valid29 || _valid0; -} -if(!valid29){ -const err136 = {instancePath:instancePath+"/messages/" + i0+"/message/content",schemaPath:"#/properties/messages/items/properties/message/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -else { -errors = _errs205; -if(vErrors !== null){ -if(_errs205){ -vErrors.length = _errs205; -} -else { -vErrors = null; -} -} -} -} -if(data51.tool_calls !== undefined){ -let data102 = data51.tool_calls; -if((data102 !== null) && (!(Array.isArray(data102)))){ -const err137 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -if(Array.isArray(data102)){ -const len8 = data102.length; -for(let i8=0; i8<len8; i8++){ -let data103 = data102[i8]; -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.id === undefined){ -const err138 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -if(data103.type === undefined){ -const err139 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -if(data103.function === undefined){ -const err140 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -if(data103.id !== undefined){ -if(typeof data103.id !== "string"){ -const err141 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/id",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -if(data103.type !== undefined){ -if(typeof data103.type !== "string"){ -const err142 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/type",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data103.function !== undefined){ -let data106 = data103.function; -if(data106 && typeof data106 == "object" && !Array.isArray(data106)){ -if(data106.name === undefined){ -const err143 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -if(data106.arguments === undefined){ -const err144 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(data106.name !== undefined){ -if(typeof data106.name !== "string"){ -const err145 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function/name",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -if(data106.arguments !== undefined){ -if(typeof data106.arguments !== "string"){ -const err146 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function/arguments",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -} -else { -const err147 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/function",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -if(data103.duration_ms !== undefined){ -let data109 = data103.duration_ms; -if(!((typeof data109 == "number") && (!(data109 % 1) && !isNaN(data109)))){ -const err148 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/duration_ms",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data103.exit_code !== undefined){ -let data110 = data103.exit_code; -if(!((typeof data110 == "number") && (!(data110 % 1) && !isNaN(data110)))){ -const err149 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8+"/exit_code",schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -} -else { -const err150 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_calls/" + i8,schemaPath:"#/properties/messages/items/properties/message/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -} -} -if(data51.tool_call_id !== undefined){ -if(typeof data51.tool_call_id !== "string"){ -const err151 = {instancePath:instancePath+"/messages/" + i0+"/message/tool_call_id",schemaPath:"#/properties/messages/items/properties/message/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data51.name !== undefined){ -if(typeof data51.name !== "string"){ -const err152 = {instancePath:instancePath+"/messages/" + i0+"/message/name",schemaPath:"#/properties/messages/items/properties/message/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data51.authored !== undefined){ -if(typeof data51.authored !== "boolean"){ -const err153 = {instancePath:instancePath+"/messages/" + i0+"/message/authored",schemaPath:"#/properties/messages/items/properties/message/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -if(data51.sent_at !== undefined){ -let data114 = data51.sent_at; -if((data114 !== null) && (typeof data114 !== "string")){ -const err154 = {instancePath:instancePath+"/messages/" + i0+"/message/sent_at",schemaPath:"#/properties/messages/items/properties/message/properties/sent_at/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -} -if(data51.usage !== undefined){ -let data115 = data51.usage; -if((data115 !== null) && (!(data115 && typeof data115 == "object" && !Array.isArray(data115)))){ -const err155 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -if(data115 && typeof data115 == "object" && !Array.isArray(data115)){ -if(data115.prompt_tokens === undefined){ -const err156 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -if(data115.completion_tokens === undefined){ -const err157 = {instancePath:instancePath+"/messages/" + i0+"/message/usage",schemaPath:"#/properties/messages/items/properties/message/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -if(data115.reported !== undefined){ -if(typeof data115.reported !== "boolean"){ -const err158 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/reported",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -} -if(data115.cost !== undefined){ -let data117 = data115.cost; -if((data117 !== null) && (!(typeof data117 == "number"))){ -const err159 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/cost",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/cost/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -} -if(data115.prompt_tokens !== undefined){ -let data118 = data115.prompt_tokens; -if(!((typeof data118 == "number") && (!(data118 % 1) && !isNaN(data118)))){ -const err160 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data115.completion_tokens !== undefined){ -let data119 = data115.completion_tokens; -if(!((typeof data119 == "number") && (!(data119 % 1) && !isNaN(data119)))){ -const err161 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -} -if(data115.prompt_tokens_details !== undefined){ -let data120 = data115.prompt_tokens_details; -if((data120 !== null) && (!(data120 && typeof data120 == "object" && !Array.isArray(data120)))){ -const err162 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.cached_tokens === undefined){ -const err163 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -if(data120.cached_tokens !== undefined){ -let data121 = data120.cached_tokens; -if(!((typeof data121 == "number") && (!(data121 % 1) && !isNaN(data121)))){ -const err164 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -} -} -if(data115.completion_tokens_details !== undefined){ -let data122 = data115.completion_tokens_details; -if((data122 !== null) && (!(data122 && typeof data122 == "object" && !Array.isArray(data122)))){ -const err165 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.message.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -if(data122 && typeof data122 == "object" && !Array.isArray(data122)){ -if(data122.reasoning_tokens === undefined){ -const err166 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -if(data122.reasoning_tokens !== undefined){ -let data123 = data122.reasoning_tokens; -if(!((typeof data123 == "number") && (!(data123 % 1) && !isNaN(data123)))){ -const err167 = {instancePath:instancePath+"/messages/" + i0+"/message/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/messages/items/properties/message/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -} -} -} -} -if(data51.model !== undefined){ -if(typeof data51.model !== "string"){ -const err168 = {instancePath:instancePath+"/messages/" + i0+"/message/model",schemaPath:"#/properties/messages/items/properties/message/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -} -if(data51.rewound_from !== undefined){ -if(typeof data51.rewound_from !== "string"){ -const err169 = {instancePath:instancePath+"/messages/" + i0+"/message/rewound_from",schemaPath:"#/properties/messages/items/properties/message/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -} -if(data51.call_id !== undefined){ -if(typeof data51.call_id !== "string"){ -const err170 = {instancePath:instancePath+"/messages/" + i0+"/message/call_id",schemaPath:"#/properties/messages/items/properties/message/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -} -} -} -if(data5.body !== undefined){ -let data127 = data5.body; -if((data127 !== null) && (!(data127 && typeof data127 == "object" && !Array.isArray(data127)))){ -const err171 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -if(data127 && typeof data127 == "object" && !Array.isArray(data127)){ -if(data127.reference_id === undefined){ -const err172 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -if(data127.digest === undefined){ -const err173 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -if(data127.size === undefined){ -const err174 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -if(data127.media_type === undefined){ -const err175 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -if(data127.source === undefined){ -const err176 = {instancePath:instancePath+"/messages/" + i0+"/body",schemaPath:"#/properties/messages/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -if(data127.text !== undefined){ -let data128 = data127.text; -if((data128 !== null) && (typeof data128 !== "string")){ -const err177 = {instancePath:instancePath+"/messages/" + i0+"/body/text",schemaPath:"#/properties/messages/items/properties/body/properties/text/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -if(data127.binary !== undefined){ -let data129 = data127.binary; -if((typeof data129 !== "string") && (data129 !== null)){ -const err178 = {instancePath:instancePath+"/messages/" + i0+"/body/binary",schemaPath:"#/properties/messages/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema19.properties.messages.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -if(data127.reference_id !== undefined){ -if(typeof data127.reference_id !== "string"){ -const err179 = {instancePath:instancePath+"/messages/" + i0+"/body/reference_id",schemaPath:"#/properties/messages/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -if(data127.digest !== undefined){ -if(typeof data127.digest !== "string"){ -const err180 = {instancePath:instancePath+"/messages/" + i0+"/body/digest",schemaPath:"#/properties/messages/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -} -if(data127.size !== undefined){ -let data132 = data127.size; -if(typeof data132 === "string"){ -if(!pattern0.test(data132)){ -const err181 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -if(!(formats0.validate(data132))){ -const err182 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -} -else { -const err183 = {instancePath:instancePath+"/messages/" + i0+"/body/size",schemaPath:"#/properties/messages/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -} -if(data127.media_type !== undefined){ -if(typeof data127.media_type !== "string"){ -const err184 = {instancePath:instancePath+"/messages/" + i0+"/body/media_type",schemaPath:"#/properties/messages/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -} -if(data127.source !== undefined){ -if(typeof data127.source !== "string"){ -const err185 = {instancePath:instancePath+"/messages/" + i0+"/body/source",schemaPath:"#/properties/messages/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -} -} -} -else { -const err186 = {instancePath:instancePath+"/messages/" + i0,schemaPath:"#/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -} -} -} -} -else { -const err187 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -validate18.errors = vErrors; -return errors === 0; -} - -export const BrowserCommand = validate19; -const schema20 = {"type":"object","properties":{"command_id":{"type":"string"},"operation_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"provider_epoch":{"type":"string"},"scope":{"type":"object","properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":true},"expected_document":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/BrowserCommand","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommand","required":["command_id","operation_id","root_id","agent_id","provider_epoch","scope","deadline_millis","kind","arguments"],"additionalProperties":true}; - -function validate19(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommand" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.operation_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.scope === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.kind === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.arguments === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err9 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err10 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err11 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err12 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err13 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.scope !== undefined){ -let data5 = data.scope; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.provider_id === undefined){ -const err14 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data5.provider_epoch === undefined){ -const err15 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data5.tab_id === undefined){ -const err16 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data5.tab_generation === undefined){ -const err17 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data5.profile_id === undefined){ -const err18 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data5.rights === undefined){ -const err19 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data5.provider_id !== undefined){ -if(typeof data5.provider_id !== "string"){ -const err20 = {instancePath:instancePath+"/scope/provider_id",schemaPath:"#/properties/scope/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data5.provider_epoch !== undefined){ -if(typeof data5.provider_epoch !== "string"){ -const err21 = {instancePath:instancePath+"/scope/provider_epoch",schemaPath:"#/properties/scope/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data5.tab_id !== undefined){ -if(typeof data5.tab_id !== "string"){ -const err22 = {instancePath:instancePath+"/scope/tab_id",schemaPath:"#/properties/scope/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data5.tab_generation !== undefined){ -if(typeof data5.tab_generation !== "string"){ -const err23 = {instancePath:instancePath+"/scope/tab_generation",schemaPath:"#/properties/scope/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data5.profile_id !== undefined){ -if(typeof data5.profile_id !== "string"){ -const err24 = {instancePath:instancePath+"/scope/profile_id",schemaPath:"#/properties/scope/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data5.attachment_id !== undefined){ -if(typeof data5.attachment_id !== "string"){ -const err25 = {instancePath:instancePath+"/scope/attachment_id",schemaPath:"#/properties/scope/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data5.attachment_generation !== undefined){ -if(typeof data5.attachment_generation !== "string"){ -const err26 = {instancePath:instancePath+"/scope/attachment_generation",schemaPath:"#/properties/scope/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data5.rights !== undefined){ -let data13 = data5.rights; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err27 = {instancePath:instancePath+"/scope/rights",schemaPath:"#/properties/scope/properties/rights/type",keyword:"type",params:{type: schema20.properties.scope.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(Array.isArray(data13)){ -const len0 = data13.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data13[i0] !== "string"){ -const err28 = {instancePath:instancePath+"/scope/rights/" + i0,schemaPath:"#/properties/scope/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -if(data5.preview !== undefined){ -let data15 = data5.preview; -if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err29 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/type",keyword:"type",params:{type: schema20.properties.scope.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.host_id === undefined){ -const err30 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data15.host_identity === undefined){ -const err31 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data15.connection_generation === undefined){ -const err32 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data15.environment_id === undefined){ -const err33 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data15.loopback === undefined){ -const err34 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data15.ports === undefined){ -const err35 = {instancePath:instancePath+"/scope/preview",schemaPath:"#/properties/scope/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data15.host_id !== undefined){ -if(typeof data15.host_id !== "string"){ -const err36 = {instancePath:instancePath+"/scope/preview/host_id",schemaPath:"#/properties/scope/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data15.host_identity !== undefined){ -if(typeof data15.host_identity !== "string"){ -const err37 = {instancePath:instancePath+"/scope/preview/host_identity",schemaPath:"#/properties/scope/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data15.connection_generation !== undefined){ -if(typeof data15.connection_generation !== "string"){ -const err38 = {instancePath:instancePath+"/scope/preview/connection_generation",schemaPath:"#/properties/scope/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data15.environment_id !== undefined){ -if(typeof data15.environment_id !== "string"){ -const err39 = {instancePath:instancePath+"/scope/preview/environment_id",schemaPath:"#/properties/scope/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data15.loopback !== undefined){ -if(typeof data15.loopback !== "string"){ -const err40 = {instancePath:instancePath+"/scope/preview/loopback",schemaPath:"#/properties/scope/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data15.ports !== undefined){ -let data21 = data15.ports; -if((data21 !== null) && (!(Array.isArray(data21)))){ -const err41 = {instancePath:instancePath+"/scope/preview/ports",schemaPath:"#/properties/scope/properties/preview/properties/ports/type",keyword:"type",params:{type: schema20.properties.scope.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(Array.isArray(data21)){ -const len1 = data21.length; -for(let i1=0; i1<len1; i1++){ -let data22 = data21[i1]; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err42 = {instancePath:instancePath+"/scope/preview/ports/" + i1,schemaPath:"#/properties/scope/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -} -} -} -} -else { -const err43 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data.expected_document !== undefined){ -if(typeof data.expected_document !== "string"){ -const err44 = {instancePath:instancePath+"/expected_document",schemaPath:"#/properties/expected_document/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data24 = data.deadline_millis; -if(typeof data24 === "string"){ -if(!pattern0.test(data24)){ -const err45 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(!(formats0.validate(data24))){ -const err46 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -else { -const err47 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err48 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -} -else { -const err49 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -validate19.errors = vErrors; -return errors === 0; -} - -export const BrowserCommandCancel = validate20; -const schema21 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"attachment_generation":{"type":"string"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserCommandCancel","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommandCancel","required":["command_id","root_id","provider_epoch","attachment_generation","reason"],"additionalProperties":true}; - -function validate20(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommandCancel" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.reason === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err5 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err7 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err8 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err9 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate20.errors = vErrors; -return errors === 0; -} - -export const BrowserCommandResultParams = validate21; -const schema22 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"attachment_generation":{"type":"string"},"document_revision":{"type":"string"},"result":true,"error":{"type":["null","object"],"properties":{"kind":{"type":"string"},"message":{"type":"string"}},"required":["kind","message"],"additionalProperties":true},"screenshot":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/BrowserCommandResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserCommandResultParams","required":["command_id","root_id","provider_epoch","attachment_generation","document_revision"],"additionalProperties":true}; - -function validate21(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserCommandResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.document_revision === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err5 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err7 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err8 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.document_revision !== undefined){ -if(typeof data.document_revision !== "string"){ -const err9 = {instancePath:instancePath+"/document_revision",schemaPath:"#/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.error !== undefined){ -let data5 = data.error; -if((data5 !== null) && (!(data5 && typeof data5 == "object" && !Array.isArray(data5)))){ -const err10 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema22.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.kind === undefined){ -const err11 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data5.message === undefined){ -const err12 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data5.kind !== undefined){ -if(typeof data5.kind !== "string"){ -const err13 = {instancePath:instancePath+"/error/kind",schemaPath:"#/properties/error/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data5.message !== undefined){ -if(typeof data5.message !== "string"){ -const err14 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.screenshot !== undefined){ -let data8 = data.screenshot; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err15 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/type",keyword:"type",params:{type: schema22.properties.screenshot.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.reference_id === undefined){ -const err16 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data8.digest === undefined){ -const err17 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data8.size === undefined){ -const err18 = {instancePath:instancePath+"/screenshot",schemaPath:"#/properties/screenshot/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data8.reference_id !== undefined){ -if(typeof data8.reference_id !== "string"){ -const err19 = {instancePath:instancePath+"/screenshot/reference_id",schemaPath:"#/properties/screenshot/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data8.digest !== undefined){ -if(typeof data8.digest !== "string"){ -const err20 = {instancePath:instancePath+"/screenshot/digest",schemaPath:"#/properties/screenshot/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data8.size !== undefined){ -let data11 = data8.size; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err21 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err22 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/screenshot/size",schemaPath:"#/properties/screenshot/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data8.media_type !== undefined){ -if(typeof data8.media_type !== "string"){ -const err24 = {instancePath:instancePath+"/screenshot/media_type",schemaPath:"#/properties/screenshot/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data8.source !== undefined){ -if(typeof data8.source !== "string"){ -const err25 = {instancePath:instancePath+"/screenshot/source",schemaPath:"#/properties/screenshot/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -} -else { -const err26 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -validate21.errors = vErrors; -return errors === 0; -} - -export const BrowserDriverParams = validate22; -const schema23 = {"type":"object","properties":{"driver":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserDriverParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserDriverParams","required":["driver"],"additionalProperties":true}; - -function validate22(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserDriverParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.driver === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "driver"},message:"must have required property '"+"driver"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.driver !== undefined){ -if(typeof data.driver !== "string"){ -const err1 = {instancePath:instancePath+"/driver",schemaPath:"#/properties/driver/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate22.errors = vErrors; -return errors === 0; -} - -export const BrowserInventoryRequest = validate23; -const schema24 = {"type":"object","properties":{"request_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"}},"required":["tab_id","tab_generation"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/BrowserInventoryRequest","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserInventoryRequest","required":["request_id","root_id","agent_id","provider_id","provider_epoch","tabs"],"additionalProperties":true}; - -function validate23(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserInventoryRequest" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.request_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "request_id"},message:"must have required property '"+"request_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.agent_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.provider_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.tabs === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tabs"},message:"must have required property '"+"tabs"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.request_id !== undefined){ -if(typeof data.request_id !== "string"){ -const err6 = {instancePath:instancePath+"/request_id",schemaPath:"#/properties/request_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err8 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err9 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err10 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.tabs !== undefined){ -let data5 = data.tabs; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err11 = {instancePath:instancePath+"/tabs",schemaPath:"#/properties/tabs/type",keyword:"type",params:{type: schema24.properties.tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -let data6 = data5[i0]; -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.tab_id === undefined){ -const err12 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data6.tab_generation === undefined){ -const err13 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data6.tab_id !== undefined){ -if(typeof data6.tab_id !== "string"){ -const err14 = {instancePath:instancePath+"/tabs/" + i0+"/tab_id",schemaPath:"#/properties/tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data6.tab_generation !== undefined){ -if(typeof data6.tab_generation !== "string"){ -const err15 = {instancePath:instancePath+"/tabs/" + i0+"/tab_generation",schemaPath:"#/properties/tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate23.errors = vErrors; -return errors === 0; -} - -export const BrowserInventoryResultParams = validate24; -const schema25 = {"type":"object","properties":{"request_id":{"type":"string"},"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"document_revision":{"type":"string"},"url":{"type":"string"},"title":{"type":"string"},"state":{"type":"string"},"requestable":{"type":"boolean"},"attachment_id":{"type":"string"}},"required":["tab_id","tab_generation","document_revision","url","title","state","requestable"],"additionalProperties":true}},"error":{"type":["null","object"],"properties":{"kind":{"type":"string"},"message":{"type":"string"}},"required":["kind","message"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/BrowserInventoryResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserInventoryResultParams","required":["request_id","root_id","provider_epoch","tabs"],"additionalProperties":true}; - -function validate24(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserInventoryResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.request_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "request_id"},message:"must have required property '"+"request_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.tabs === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tabs"},message:"must have required property '"+"tabs"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.request_id !== undefined){ -if(typeof data.request_id !== "string"){ -const err4 = {instancePath:instancePath+"/request_id",schemaPath:"#/properties/request_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err6 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.tabs !== undefined){ -let data3 = data.tabs; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err7 = {instancePath:instancePath+"/tabs",schemaPath:"#/properties/tabs/type",keyword:"type",params:{type: schema25.properties.tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.tab_id === undefined){ -const err8 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.tab_generation === undefined){ -const err9 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.document_revision === undefined){ -const err10 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.url === undefined){ -const err11 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data4.title === undefined){ -const err12 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data4.state === undefined){ -const err13 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data4.requestable === undefined){ -const err14 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/required",keyword:"required",params:{missingProperty: "requestable"},message:"must have required property '"+"requestable"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data4.tab_id !== undefined){ -if(typeof data4.tab_id !== "string"){ -const err15 = {instancePath:instancePath+"/tabs/" + i0+"/tab_id",schemaPath:"#/properties/tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data4.tab_generation !== undefined){ -if(typeof data4.tab_generation !== "string"){ -const err16 = {instancePath:instancePath+"/tabs/" + i0+"/tab_generation",schemaPath:"#/properties/tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data4.document_revision !== undefined){ -if(typeof data4.document_revision !== "string"){ -const err17 = {instancePath:instancePath+"/tabs/" + i0+"/document_revision",schemaPath:"#/properties/tabs/items/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data4.url !== undefined){ -if(typeof data4.url !== "string"){ -const err18 = {instancePath:instancePath+"/tabs/" + i0+"/url",schemaPath:"#/properties/tabs/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data4.title !== undefined){ -if(typeof data4.title !== "string"){ -const err19 = {instancePath:instancePath+"/tabs/" + i0+"/title",schemaPath:"#/properties/tabs/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data4.state !== undefined){ -if(typeof data4.state !== "string"){ -const err20 = {instancePath:instancePath+"/tabs/" + i0+"/state",schemaPath:"#/properties/tabs/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data4.requestable !== undefined){ -if(typeof data4.requestable !== "boolean"){ -const err21 = {instancePath:instancePath+"/tabs/" + i0+"/requestable",schemaPath:"#/properties/tabs/items/properties/requestable/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data4.attachment_id !== undefined){ -if(typeof data4.attachment_id !== "string"){ -const err22 = {instancePath:instancePath+"/tabs/" + i0+"/attachment_id",schemaPath:"#/properties/tabs/items/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath:instancePath+"/tabs/" + i0,schemaPath:"#/properties/tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data.error !== undefined){ -let data13 = data.error; -if((data13 !== null) && (!(data13 && typeof data13 == "object" && !Array.isArray(data13)))){ -const err24 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema25.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.kind === undefined){ -const err25 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data13.message === undefined){ -const err26 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data13.kind !== undefined){ -if(typeof data13.kind !== "string"){ -const err27 = {instancePath:instancePath+"/error/kind",schemaPath:"#/properties/error/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data13.message !== undefined){ -if(typeof data13.message !== "string"){ -const err28 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -} -else { -const err29 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -validate24.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderBindParams = validate25; -const schema26 = {"type":"object","properties":{"availability":{"type":"boolean"},"root_id":{"type":"string"},"version":{"type":"integer"},"desktop_id":{"type":"string"},"window_id":{"type":"string"},"offer_revision":{"type":"string"},"create_profile_id":{"type":"string"},"expected_provider_epoch":{"type":"string"},"offered_tabs":{"type":["null","array"],"items":{"type":"object","properties":{"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"document_revision":{"type":"string"},"url":{"type":"string"},"title":{"type":"string"},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["tab_id","tab_generation","profile_id"],"additionalProperties":true}},"offered_preview_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/BrowserProviderBindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderBindParams","required":["root_id","version","desktop_id","window_id","offer_revision","create_profile_id","offered_tabs","offered_preview_hosts"],"additionalProperties":true}; - -function validate25(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderBindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.version === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.desktop_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "desktop_id"},message:"must have required property '"+"desktop_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.window_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "window_id"},message:"must have required property '"+"window_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.offer_revision === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offer_revision"},message:"must have required property '"+"offer_revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.create_profile_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "create_profile_id"},message:"must have required property '"+"create_profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.offered_tabs === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered_tabs"},message:"must have required property '"+"offered_tabs"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.offered_preview_hosts === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered_preview_hosts"},message:"must have required property '"+"offered_preview_hosts"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.availability !== undefined){ -if(typeof data.availability !== "boolean"){ -const err8 = {instancePath:instancePath+"/availability",schemaPath:"#/properties/availability/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err9 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.version !== undefined){ -let data2 = data.version; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err10 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.desktop_id !== undefined){ -if(typeof data.desktop_id !== "string"){ -const err11 = {instancePath:instancePath+"/desktop_id",schemaPath:"#/properties/desktop_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.window_id !== undefined){ -if(typeof data.window_id !== "string"){ -const err12 = {instancePath:instancePath+"/window_id",schemaPath:"#/properties/window_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.offer_revision !== undefined){ -if(typeof data.offer_revision !== "string"){ -const err13 = {instancePath:instancePath+"/offer_revision",schemaPath:"#/properties/offer_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.create_profile_id !== undefined){ -if(typeof data.create_profile_id !== "string"){ -const err14 = {instancePath:instancePath+"/create_profile_id",schemaPath:"#/properties/create_profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.expected_provider_epoch !== undefined){ -if(typeof data.expected_provider_epoch !== "string"){ -const err15 = {instancePath:instancePath+"/expected_provider_epoch",schemaPath:"#/properties/expected_provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.offered_tabs !== undefined){ -let data8 = data.offered_tabs; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err16 = {instancePath:instancePath+"/offered_tabs",schemaPath:"#/properties/offered_tabs/type",keyword:"type",params:{type: schema26.properties.offered_tabs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data8)){ -const len0 = data8.length; -for(let i0=0; i0<len0; i0++){ -let data9 = data8[i0]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.tab_id === undefined){ -const err17 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data9.tab_generation === undefined){ -const err18 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data9.profile_id === undefined){ -const err19 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data9.tab_id !== undefined){ -if(typeof data9.tab_id !== "string"){ -const err20 = {instancePath:instancePath+"/offered_tabs/" + i0+"/tab_id",schemaPath:"#/properties/offered_tabs/items/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data9.tab_generation !== undefined){ -if(typeof data9.tab_generation !== "string"){ -const err21 = {instancePath:instancePath+"/offered_tabs/" + i0+"/tab_generation",schemaPath:"#/properties/offered_tabs/items/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data9.profile_id !== undefined){ -if(typeof data9.profile_id !== "string"){ -const err22 = {instancePath:instancePath+"/offered_tabs/" + i0+"/profile_id",schemaPath:"#/properties/offered_tabs/items/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data9.document_revision !== undefined){ -if(typeof data9.document_revision !== "string"){ -const err23 = {instancePath:instancePath+"/offered_tabs/" + i0+"/document_revision",schemaPath:"#/properties/offered_tabs/items/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data9.url !== undefined){ -if(typeof data9.url !== "string"){ -const err24 = {instancePath:instancePath+"/offered_tabs/" + i0+"/url",schemaPath:"#/properties/offered_tabs/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data9.title !== undefined){ -if(typeof data9.title !== "string"){ -const err25 = {instancePath:instancePath+"/offered_tabs/" + i0+"/title",schemaPath:"#/properties/offered_tabs/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data9.preview !== undefined){ -let data16 = data9.preview; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err26 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/type",keyword:"type",params:{type: schema26.properties.offered_tabs.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.host_id === undefined){ -const err27 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data16.host_identity === undefined){ -const err28 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data16.connection_generation === undefined){ -const err29 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data16.environment_id === undefined){ -const err30 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data16.loopback === undefined){ -const err31 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data16.ports === undefined){ -const err32 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview",schemaPath:"#/properties/offered_tabs/items/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data16.host_id !== undefined){ -if(typeof data16.host_id !== "string"){ -const err33 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/host_id",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data16.host_identity !== undefined){ -if(typeof data16.host_identity !== "string"){ -const err34 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/host_identity",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data16.connection_generation !== undefined){ -if(typeof data16.connection_generation !== "string"){ -const err35 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/connection_generation",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data16.environment_id !== undefined){ -if(typeof data16.environment_id !== "string"){ -const err36 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/environment_id",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data16.loopback !== undefined){ -if(typeof data16.loopback !== "string"){ -const err37 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/loopback",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data16.ports !== undefined){ -let data22 = data16.ports; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err38 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/ports",schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/ports/type",keyword:"type",params:{type: schema26.properties.offered_tabs.items.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(Array.isArray(data22)){ -const len1 = data22.length; -for(let i1=0; i1<len1; i1++){ -let data23 = data22[i1]; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err39 = {instancePath:instancePath+"/offered_tabs/" + i0+"/preview/ports/" + i1,schemaPath:"#/properties/offered_tabs/items/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -} -} -} -} -} -else { -const err40 = {instancePath:instancePath+"/offered_tabs/" + i0,schemaPath:"#/properties/offered_tabs/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -} -} -if(data.offered_preview_hosts !== undefined){ -let data24 = data.offered_preview_hosts; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err41 = {instancePath:instancePath+"/offered_preview_hosts",schemaPath:"#/properties/offered_preview_hosts/type",keyword:"type",params:{type: schema26.properties.offered_preview_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(Array.isArray(data24)){ -const len2 = data24.length; -for(let i2=0; i2<len2; i2++){ -let data25 = data24[i2]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.host_id === undefined){ -const err42 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data25.host_identity === undefined){ -const err43 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data25.connection_generation === undefined){ -const err44 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data25.environment_id === undefined){ -const err45 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data25.loopback === undefined){ -const err46 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data25.ports === undefined){ -const err47 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data25.host_id !== undefined){ -if(typeof data25.host_id !== "string"){ -const err48 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/host_id",schemaPath:"#/properties/offered_preview_hosts/items/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data25.host_identity !== undefined){ -if(typeof data25.host_identity !== "string"){ -const err49 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/host_identity",schemaPath:"#/properties/offered_preview_hosts/items/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data25.connection_generation !== undefined){ -if(typeof data25.connection_generation !== "string"){ -const err50 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/connection_generation",schemaPath:"#/properties/offered_preview_hosts/items/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data25.environment_id !== undefined){ -if(typeof data25.environment_id !== "string"){ -const err51 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/environment_id",schemaPath:"#/properties/offered_preview_hosts/items/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data25.loopback !== undefined){ -if(typeof data25.loopback !== "string"){ -const err52 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/loopback",schemaPath:"#/properties/offered_preview_hosts/items/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data25.ports !== undefined){ -let data31 = data25.ports; -if((data31 !== null) && (!(Array.isArray(data31)))){ -const err53 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/ports",schemaPath:"#/properties/offered_preview_hosts/items/properties/ports/type",keyword:"type",params:{type: schema26.properties.offered_preview_hosts.items.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(Array.isArray(data31)){ -const len3 = data31.length; -for(let i3=0; i3<len3; i3++){ -let data32 = data31[i3]; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err54 = {instancePath:instancePath+"/offered_preview_hosts/" + i2+"/ports/" + i3,schemaPath:"#/properties/offered_preview_hosts/items/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -} -} -} -else { -const err55 = {instancePath:instancePath+"/offered_preview_hosts/" + i2,schemaPath:"#/properties/offered_preview_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -} -} -} -else { -const err56 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -validate25.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderBindResult = validate26; -const schema27 = {"type":"object","properties":{"version":{"type":"integer"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderBindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderBindResult","required":["version","provider_id","provider_epoch"],"additionalProperties":true}; - -function validate26(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderBindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.version === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.version !== undefined){ -let data0 = data.version; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err3 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err4 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err5 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate26.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderEventParams = validate27; -const schema28 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"sequence":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"operation_id":{"type":"string"},"document_revision":{"type":"string"},"kind":{"type":"string"},"method":{"type":"string"},"params":true,"url":{"type":"string"},"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderEventParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderEventParams","required":["root_id","provider_epoch","tab_id","tab_generation","attachment_id","attachment_generation","sequence","document_revision","kind"],"additionalProperties":true}; - -function validate27(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderEventParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.tab_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.tab_generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.attachment_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_id"},message:"must have required property '"+"attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.attachment_generation === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "attachment_generation"},message:"must have required property '"+"attachment_generation"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.sequence === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "sequence"},message:"must have required property '"+"sequence"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.document_revision === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "document_revision"},message:"must have required property '"+"document_revision"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.kind === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err9 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err10 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.tab_id !== undefined){ -if(typeof data.tab_id !== "string"){ -const err11 = {instancePath:instancePath+"/tab_id",schemaPath:"#/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.tab_generation !== undefined){ -if(typeof data.tab_generation !== "string"){ -const err12 = {instancePath:instancePath+"/tab_generation",schemaPath:"#/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.attachment_id !== undefined){ -if(typeof data.attachment_id !== "string"){ -const err13 = {instancePath:instancePath+"/attachment_id",schemaPath:"#/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.attachment_generation !== undefined){ -if(typeof data.attachment_generation !== "string"){ -const err14 = {instancePath:instancePath+"/attachment_generation",schemaPath:"#/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.sequence !== undefined){ -let data6 = data.sequence; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err15 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err16 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err18 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.document_revision !== undefined){ -if(typeof data.document_revision !== "string"){ -const err19 = {instancePath:instancePath+"/document_revision",schemaPath:"#/properties/document_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err20 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.method !== undefined){ -if(typeof data.method !== "string"){ -const err21 = {instancePath:instancePath+"/method",schemaPath:"#/properties/method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.url !== undefined){ -if(typeof data.url !== "string"){ -const err22 = {instancePath:instancePath+"/url",schemaPath:"#/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err23 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -validate27.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderRevoked = validate28; -const schema29 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderRevoked","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderRevoked","required":["root_id","provider_id","provider_epoch","reason"],"additionalProperties":true}; - -function validate28(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderRevoked" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.reason === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider_id !== undefined){ -if(typeof data.provider_id !== "string"){ -const err5 = {instancePath:instancePath+"/provider_id",schemaPath:"#/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err6 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err7 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate28.errors = vErrors; -return errors === 0; -} - -export const BrowserProviderUnbindParams = validate29; -const schema30 = {"type":"object","properties":{"root_id":{"type":"string"},"provider_epoch":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserProviderUnbindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserProviderUnbindParams","required":["root_id","provider_epoch"],"additionalProperties":true}; - -function validate29(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserProviderUnbindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider_epoch === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider_epoch !== undefined){ -if(typeof data.provider_epoch !== "string"){ -const err3 = {instancePath:instancePath+"/provider_epoch",schemaPath:"#/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate29.errors = vErrors; -return errors === 0; -} - -export const BrowserStatusResult = validate30; -const schema31 = {"type":"object","properties":{"enabled":{"type":"boolean"},"driver":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/BrowserStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"BrowserStatusResult","required":["enabled"],"additionalProperties":true}; - -function validate30(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BrowserStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.enabled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err1 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.driver !== undefined){ -if(typeof data.driver !== "string"){ -const err2 = {instancePath:instancePath+"/driver",schemaPath:"#/properties/driver/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate30.errors = vErrors; -return errors === 0; -} - -export const BudgetCapParams = validate31; -const schema32 = {"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/BudgetCapParams","$schema":"http://json-schema.org/draft-07/schema#","title":"BudgetCapParams","required":["id","kind","limit"],"additionalProperties":true}; - -function validate31(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BudgetCapParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.kind === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err4 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.limit !== undefined){ -let data2 = data.limit; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err5 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err6 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate31.errors = vErrors; -return errors === 0; -} - -export const BudgetState = validate32; -const schema33 = {"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/BudgetState","$schema":"http://json-schema.org/draft-07/schema#","title":"BudgetState","required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":true}; - -function validate32(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/BudgetState" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.kind === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.limit === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.used === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.reserved === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.remaining === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.uncertain === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.incomplete === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err7 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.limit !== undefined){ -let data1 = data.limit; -if((typeof data1 !== "string") && (data1 !== null)){ -const err8 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: schema33.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err9 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err10 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -if(data.used !== undefined){ -let data2 = data.used; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err11 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err12 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -else { -const err13 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.reserved !== undefined){ -let data3 = data.reserved; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err14 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err15 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -else { -const err16 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.remaining !== undefined){ -let data4 = data.remaining; -if((typeof data4 !== "string") && (data4 !== null)){ -const err17 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/type",keyword:"type",params:{type: schema33.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err18 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err19 = {instancePath:instancePath+"/remaining",schemaPath:"#/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -if(data.uncertain !== undefined){ -let data5 = data.uncertain; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err20 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err21 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -else { -const err22 = {instancePath:instancePath+"/uncertain",schemaPath:"#/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.incomplete !== undefined){ -if(typeof data.incomplete !== "boolean"){ -const err23 = {instancePath:instancePath+"/incomplete",schemaPath:"#/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -validate32.errors = vErrors; -return errors === 0; -} - -export const CancelParams = validate33; -const schema34 = {"type":"object","properties":{"turn_id":{"type":"string"},"target_command_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CancelParams","additionalProperties":true}; - -function validate33(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err0 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.target_command_id !== undefined){ -if(typeof data.target_command_id !== "string"){ -const err1 = {instancePath:instancePath+"/target_command_id",schemaPath:"#/properties/target_command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate33.errors = vErrors; -return errors === 0; -} - -export const CapabilityRecord = validate34; -const schema35 = {"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":true}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":true},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CapabilityRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"CapabilityRecord","required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":true}; - -function validate34(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CapabilityRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.agent_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.issuer_agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.operations === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.scopes === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.mcp === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.mcp_all === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.generation === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.status === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.expires_at === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.created_at === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.updated_at === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err13 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err14 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err15 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.issuer_agent_id !== undefined){ -if(typeof data.issuer_agent_id !== "string"){ -const err16 = {instancePath:instancePath+"/issuer_agent_id",schemaPath:"#/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.operations !== undefined){ -let data4 = data.operations; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err17 = {instancePath:instancePath+"/operations",schemaPath:"#/properties/operations/type",keyword:"type",params:{type: schema35.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err18 = {instancePath:instancePath+"/operations/" + i0,schemaPath:"#/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data.scopes !== undefined){ -let data6 = data.scopes; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err19 = {instancePath:instancePath+"/scopes",schemaPath:"#/properties/scopes/type",keyword:"type",params:{type: schema35.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data6[i1] !== "string"){ -const err20 = {instancePath:instancePath+"/scopes/" + i1,schemaPath:"#/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -} -if(data.file_scope !== undefined){ -if(typeof data.file_scope !== "string"){ -const err21 = {instancePath:instancePath+"/file_scope",schemaPath:"#/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.file_issuer_id !== undefined){ -if(typeof data.file_issuer_id !== "string"){ -const err22 = {instancePath:instancePath+"/file_issuer_id",schemaPath:"#/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.file_issuer_generation !== undefined){ -let data10 = data.file_issuer_generation; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err23 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err24 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/file_issuer_generation",schemaPath:"#/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data.mcp !== undefined){ -let data11 = data.mcp; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err26 = {instancePath:instancePath+"/mcp",schemaPath:"#/properties/mcp/type",keyword:"type",params:{type: schema35.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -let data12 = data11[i2]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.server === undefined){ -const err27 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data12.tool === undefined){ -const err28 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data12.definition === undefined){ -const err29 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data12.server !== undefined){ -if(typeof data12.server !== "string"){ -const err30 = {instancePath:instancePath+"/mcp/" + i2+"/server",schemaPath:"#/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data12.tool !== undefined){ -if(typeof data12.tool !== "string"){ -const err31 = {instancePath:instancePath+"/mcp/" + i2+"/tool",schemaPath:"#/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data12.definition !== undefined){ -if(typeof data12.definition !== "string"){ -const err32 = {instancePath:instancePath+"/mcp/" + i2+"/definition",schemaPath:"#/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath:instancePath+"/mcp/" + i2,schemaPath:"#/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -if(data.mcp_all !== undefined){ -if(typeof data.mcp_all !== "boolean"){ -const err34 = {instancePath:instancePath+"/mcp_all",schemaPath:"#/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data.browser !== undefined){ -let data17 = data.browser; -if((data17 !== null) && (!(data17 && typeof data17 == "object" && !Array.isArray(data17)))){ -const err35 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/type",keyword:"type",params:{type: schema35.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.provider_id === undefined){ -const err36 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data17.provider_epoch === undefined){ -const err37 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data17.tab_id === undefined){ -const err38 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data17.tab_generation === undefined){ -const err39 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data17.profile_id === undefined){ -const err40 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data17.rights === undefined){ -const err41 = {instancePath:instancePath+"/browser",schemaPath:"#/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data17.provider_id !== undefined){ -if(typeof data17.provider_id !== "string"){ -const err42 = {instancePath:instancePath+"/browser/provider_id",schemaPath:"#/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data17.provider_epoch !== undefined){ -if(typeof data17.provider_epoch !== "string"){ -const err43 = {instancePath:instancePath+"/browser/provider_epoch",schemaPath:"#/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data17.tab_id !== undefined){ -if(typeof data17.tab_id !== "string"){ -const err44 = {instancePath:instancePath+"/browser/tab_id",schemaPath:"#/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.tab_generation !== undefined){ -if(typeof data17.tab_generation !== "string"){ -const err45 = {instancePath:instancePath+"/browser/tab_generation",schemaPath:"#/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.profile_id !== undefined){ -if(typeof data17.profile_id !== "string"){ -const err46 = {instancePath:instancePath+"/browser/profile_id",schemaPath:"#/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data17.attachment_id !== undefined){ -if(typeof data17.attachment_id !== "string"){ -const err47 = {instancePath:instancePath+"/browser/attachment_id",schemaPath:"#/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data17.attachment_generation !== undefined){ -if(typeof data17.attachment_generation !== "string"){ -const err48 = {instancePath:instancePath+"/browser/attachment_generation",schemaPath:"#/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data17.rights !== undefined){ -let data25 = data17.rights; -if((data25 !== null) && (!(Array.isArray(data25)))){ -const err49 = {instancePath:instancePath+"/browser/rights",schemaPath:"#/properties/browser/properties/rights/type",keyword:"type",params:{type: schema35.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(Array.isArray(data25)){ -const len3 = data25.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data25[i3] !== "string"){ -const err50 = {instancePath:instancePath+"/browser/rights/" + i3,schemaPath:"#/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -} -if(data17.preview !== undefined){ -let data27 = data17.preview; -if((data27 !== null) && (!(data27 && typeof data27 == "object" && !Array.isArray(data27)))){ -const err51 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/type",keyword:"type",params:{type: schema35.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data27 && typeof data27 == "object" && !Array.isArray(data27)){ -if(data27.host_id === undefined){ -const err52 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data27.host_identity === undefined){ -const err53 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data27.connection_generation === undefined){ -const err54 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data27.environment_id === undefined){ -const err55 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data27.loopback === undefined){ -const err56 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data27.ports === undefined){ -const err57 = {instancePath:instancePath+"/browser/preview",schemaPath:"#/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data27.host_id !== undefined){ -if(typeof data27.host_id !== "string"){ -const err58 = {instancePath:instancePath+"/browser/preview/host_id",schemaPath:"#/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data27.host_identity !== undefined){ -if(typeof data27.host_identity !== "string"){ -const err59 = {instancePath:instancePath+"/browser/preview/host_identity",schemaPath:"#/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data27.connection_generation !== undefined){ -if(typeof data27.connection_generation !== "string"){ -const err60 = {instancePath:instancePath+"/browser/preview/connection_generation",schemaPath:"#/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data27.environment_id !== undefined){ -if(typeof data27.environment_id !== "string"){ -const err61 = {instancePath:instancePath+"/browser/preview/environment_id",schemaPath:"#/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data27.loopback !== undefined){ -if(typeof data27.loopback !== "string"){ -const err62 = {instancePath:instancePath+"/browser/preview/loopback",schemaPath:"#/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data27.ports !== undefined){ -let data33 = data27.ports; -if((data33 !== null) && (!(Array.isArray(data33)))){ -const err63 = {instancePath:instancePath+"/browser/preview/ports",schemaPath:"#/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema35.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(Array.isArray(data33)){ -const len4 = data33.length; -for(let i4=0; i4<len4; i4++){ -let data34 = data33[i4]; -if(!((typeof data34 == "number") && (!(data34 % 1) && !isNaN(data34)))){ -const err64 = {instancePath:instancePath+"/browser/preview/ports/" + i4,schemaPath:"#/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -} -} -} -} -if(data.browser_issuer_id !== undefined){ -if(typeof data.browser_issuer_id !== "string"){ -const err65 = {instancePath:instancePath+"/browser_issuer_id",schemaPath:"#/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data.browser_issuer_generation !== undefined){ -let data36 = data.browser_issuer_generation; -if(!((typeof data36 == "number") && (!(data36 % 1) && !isNaN(data36)))){ -const err66 = {instancePath:instancePath+"/browser_issuer_generation",schemaPath:"#/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data.browser_delegation_only !== undefined){ -if(typeof data.browser_delegation_only !== "boolean"){ -const err67 = {instancePath:instancePath+"/browser_delegation_only",schemaPath:"#/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data.generation !== undefined){ -let data38 = data.generation; -if(typeof data38 === "string"){ -if(!pattern0.test(data38)){ -const err68 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(!(formats0.validate(data38))){ -const err69 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -else { -const err70 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err71 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.expires_at !== undefined){ -if(typeof data.expires_at !== "string"){ -const err72 = {instancePath:instancePath+"/expires_at",schemaPath:"#/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err73 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.updated_at !== undefined){ -if(typeof data.updated_at !== "string"){ -const err74 = {instancePath:instancePath+"/updated_at",schemaPath:"#/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -} -else { -const err75 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -validate34.errors = vErrors; -return errors === 0; -} - -export const CatalogResult = validate35; -const schema36 = {"type":"object","properties":{"themes":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"dark":{"type":"boolean"},"source":{"type":"string"}},"required":["id","name","dark","source"],"additionalProperties":true}},"errors":{"type":["null","array"],"items":{"type":"object","properties":{"file":{"type":"string"},"message":{"type":"string"}},"required":["file","message"],"additionalProperties":true}},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CatalogResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CatalogResult","required":["themes","errors","truncated"],"additionalProperties":true}; - -function validate35(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CatalogResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.themes === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "themes"},message:"must have required property '"+"themes"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.errors === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "errors"},message:"must have required property '"+"errors"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.truncated === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.themes !== undefined){ -let data0 = data.themes; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/themes",schemaPath:"#/properties/themes/type",keyword:"type",params:{type: schema36.properties.themes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err4 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.name === undefined){ -const err5 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.dark === undefined){ -const err6 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "dark"},message:"must have required property '"+"dark"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.source === undefined){ -const err7 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err8 = {instancePath:instancePath+"/themes/" + i0+"/id",schemaPath:"#/properties/themes/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err9 = {instancePath:instancePath+"/themes/" + i0+"/name",schemaPath:"#/properties/themes/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.dark !== undefined){ -if(typeof data1.dark !== "boolean"){ -const err10 = {instancePath:instancePath+"/themes/" + i0+"/dark",schemaPath:"#/properties/themes/items/properties/dark/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err11 = {instancePath:instancePath+"/themes/" + i0+"/source",schemaPath:"#/properties/themes/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/themes/" + i0,schemaPath:"#/properties/themes/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.errors !== undefined){ -let data6 = data.errors; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err13 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: schema36.properties.errors.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -let data7 = data6[i1]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.file === undefined){ -const err14 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/required",keyword:"required",params:{missingProperty: "file"},message:"must have required property '"+"file"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.message === undefined){ -const err15 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7.file !== undefined){ -if(typeof data7.file !== "string"){ -const err16 = {instancePath:instancePath+"/errors/" + i1+"/file",schemaPath:"#/properties/errors/items/properties/file/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data7.message !== undefined){ -if(typeof data7.message !== "string"){ -const err17 = {instancePath:instancePath+"/errors/" + i1+"/message",schemaPath:"#/properties/errors/items/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/errors/" + i1,schemaPath:"#/properties/errors/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err19 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -validate35.errors = vErrors; -return errors === 0; -} - -export const CatalogRevision = validate36; -const schema37 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/CatalogRevision","$schema":"http://json-schema.org/draft-07/schema#","title":"CatalogRevision","required":["revision"],"additionalProperties":true}; - -function validate36(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CatalogRevision" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err1 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -else { -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate36.errors = vErrors; -return errors === 0; -} - -export const CheckpointParams = validate37; -const schema38 = {"type":"object","properties":{"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CheckpointParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CheckpointParams","additionalProperties":true}; - -function validate37(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CheckpointParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err0 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate37.errors = vErrors; -return errors === 0; -} - -export const ClearHistoryParams = validate38; -const schema39 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ClearHistoryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ClearHistoryParams","additionalProperties":true}; - -function validate38(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ClearHistoryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err0 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema39.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err1 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err2 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate38.errors = vErrors; -return errors === 0; -} - -export const CommandParams = validate39; -const schema40 = {"type":"object","properties":{"command_id":{"type":"string"},"scope":{"type":"string"},"root_id":{"type":"string"},"operation":{"type":"string"},"payload":true},"$id":"https://whip.dev/protocol/v6/CommandParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandParams","required":["command_id","scope","operation"],"additionalProperties":true}; - -function validate39(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.scope === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.operation === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err3 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.scope !== undefined){ -if(typeof data.scope !== "string"){ -const err4 = {instancePath:instancePath+"/scope",schemaPath:"#/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err6 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate39.errors = vErrors; -return errors === 0; -} - -export const CommandResult = validate40; -const schema41 = {"type":"object","properties":{"content":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"operation":{"type":"string"},"result":true,"failure":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":true},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true},"command_id":{"type":"string"},"ingress_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CommandResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandResult","required":["operation","command_id","ingress_seq","status"],"additionalProperties":true}; - -function validate40(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.command_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.ingress_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "ingress_seq"},message:"must have required property '"+"ingress_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.status === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.content !== undefined){ -let data0 = data.content; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err4 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: schema41.properties.content.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.digest === undefined){ -const err6 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.size === undefined){ -const err7 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err8 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err9 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err10 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err11 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -else { -const err12 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err13 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err14 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err15 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.failure !== undefined){ -let data7 = data.failure; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err16 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/type",keyword:"type",params:{type: schema41.properties.failure.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.code === undefined){ -const err17 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.message === undefined){ -const err18 = {instancePath:instancePath+"/failure",schemaPath:"#/properties/failure/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.data !== undefined){ -let data8 = data7.data; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err19 = {instancePath:instancePath+"/failure/data",schemaPath:"#/properties/failure/properties/data/type",keyword:"type",params:{type: schema41.properties.failure.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.kind === undefined){ -const err20 = {instancePath:instancePath+"/failure/data",schemaPath:"#/properties/failure/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data8.kind !== undefined){ -if(typeof data8.kind !== "string"){ -const err21 = {instancePath:instancePath+"/failure/data/kind",schemaPath:"#/properties/failure/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data7.code !== undefined){ -let data10 = data7.code; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err22 = {instancePath:instancePath+"/failure/code",schemaPath:"#/properties/failure/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.message !== undefined){ -if(typeof data7.message !== "string"){ -const err23 = {instancePath:instancePath+"/failure/message",schemaPath:"#/properties/failure/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err24 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.ingress_seq !== undefined){ -let data13 = data.ingress_seq; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err25 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err26 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -else { -const err27 = {instancePath:instancePath+"/ingress_seq",schemaPath:"#/properties/ingress_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err28 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -validate40.errors = vErrors; -return errors === 0; -} - -export const CommandStatusParams = validate41; -const schema42 = {"type":"object","properties":{"command_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CommandStatusParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CommandStatusParams","required":["command_id"],"additionalProperties":true}; - -function validate41(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CommandStatusParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err1 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate41.errors = vErrors; -return errors === 0; -} - -export const CompactionListResult = validate42; -const schema43 = {"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"integer"},"cutoff":{"type":"integer"},"summary":{"type":"string"}},"required":["seq","cutoff","summary"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/CompactionListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionListResult"}; - -function validate42(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema43.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.seq === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.cutoff === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cutoff"},message:"must have required property '"+"cutoff"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.summary === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "summary"},message:"must have required property '"+"summary"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.seq !== undefined){ -let data1 = data0.seq; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err4 = {instancePath:instancePath+"/" + i0+"/seq",schemaPath:"#/items/properties/seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.cutoff !== undefined){ -let data2 = data0.cutoff; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/" + i0+"/cutoff",schemaPath:"#/items/properties/cutoff/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.summary !== undefined){ -if(typeof data0.summary !== "string"){ -const err6 = {instancePath:instancePath+"/" + i0+"/summary",schemaPath:"#/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -validate42.errors = vErrors; -return errors === 0; -} - -export const CompactionParams = validate43; -const schema44 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CompactionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionParams","additionalProperties":true}; - -function validate43(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err0 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err1 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate43.errors = vErrors; -return errors === 0; -} - -export const CompactionResult = validate44; -const schema45 = {"type":"object","properties":{"cutoff":{"type":"integer"},"model":{"type":"string"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/CompactionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionResult","required":["cutoff","usage"],"additionalProperties":true}; - -function validate44(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cutoff === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cutoff"},message:"must have required property '"+"cutoff"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.usage === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cutoff !== undefined){ -let data0 = data.cutoff; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err2 = {instancePath:instancePath+"/cutoff",schemaPath:"#/properties/cutoff/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err3 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.usage !== undefined){ -let data2 = data.usage; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.prompt_tokens === undefined){ -const err4 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data2.completion_tokens === undefined){ -const err5 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2.reported !== undefined){ -if(typeof data2.reported !== "boolean"){ -const err6 = {instancePath:instancePath+"/usage/reported",schemaPath:"#/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data2.cost !== undefined){ -let data4 = data2.cost; -if((data4 !== null) && (!(typeof data4 == "number"))){ -const err7 = {instancePath:instancePath+"/usage/cost",schemaPath:"#/properties/usage/properties/cost/type",keyword:"type",params:{type: schema45.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data2.prompt_tokens !== undefined){ -let data5 = data2.prompt_tokens; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err8 = {instancePath:instancePath+"/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data2.completion_tokens !== undefined){ -let data6 = data2.completion_tokens; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err9 = {instancePath:instancePath+"/usage/completion_tokens",schemaPath:"#/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data2.prompt_tokens_details !== undefined){ -let data7 = data2.prompt_tokens_details; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err10 = {instancePath:instancePath+"/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema45.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.cached_tokens === undefined){ -const err11 = {instancePath:instancePath+"/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7.cached_tokens !== undefined){ -let data8 = data7.cached_tokens; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err12 = {instancePath:instancePath+"/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data2.completion_tokens_details !== undefined){ -let data9 = data2.completion_tokens_details; -if((data9 !== null) && (!(data9 && typeof data9 == "object" && !Array.isArray(data9)))){ -const err13 = {instancePath:instancePath+"/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema45.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.reasoning_tokens === undefined){ -const err14 = {instancePath:instancePath+"/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data9.reasoning_tokens !== undefined){ -let data10 = data9.reasoning_tokens; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err15 = {instancePath:instancePath+"/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -} -else { -const err16 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate44.errors = vErrors; -return errors === 0; -} - -export const CompactionRetryResult = validate45; -const schema46 = {"type":"object","properties":{"undone":{"type":"boolean"},"sequence":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/CompactionRetryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionRetryResult","required":["undone"],"additionalProperties":true}; - -function validate45(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionRetryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.undone === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "undone"},message:"must have required property '"+"undone"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.undone !== undefined){ -if(typeof data.undone !== "boolean"){ -const err1 = {instancePath:instancePath+"/undone",schemaPath:"#/properties/undone/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.sequence !== undefined){ -let data1 = data.sequence; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err2 = {instancePath:instancePath+"/sequence",schemaPath:"#/properties/sequence/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate45.errors = vErrors; -return errors === 0; -} - -export const CompactionSettingsResult = validate46; -const schema47 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"builtin_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CompactionSettingsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompactionSettingsResult","required":["builtin_default"],"additionalProperties":true}; - -function validate46(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompactionSettingsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.builtin_default === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "builtin_default"},message:"must have required property '"+"builtin_default"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err1 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.builtin_default !== undefined){ -if(typeof data.builtin_default !== "boolean"){ -const err3 = {instancePath:instancePath+"/builtin_default",schemaPath:"#/properties/builtin_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate46.errors = vErrors; -return errors === 0; -} - -export const CompletionParams = validate47; -const schema48 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"kind":{"type":"string"},"prefix":{"type":"string"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/CompletionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CompletionParams","required":["root_id","kind","prefix","limit"],"additionalProperties":true}; - -function validate47(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompletionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.kind === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.prefix === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "prefix"},message:"must have required property '"+"prefix"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err5 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err6 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err7 = {instancePath:instancePath+"/prefix",schemaPath:"#/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err8 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate47.errors = vErrors; -return errors === 0; -} - -export const CompletionResult = validate48; -const schema49 = {"type":"object","properties":{"warnings":{"type":["null","array"],"items":{"type":"string"}},"candidates":{"type":["null","array"],"items":{"type":"object","properties":{"text":{"type":"string"},"description":{"type":"string"}},"required":["text","description"],"additionalProperties":true}},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/CompletionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"CompletionResult","required":["candidates","truncated"],"additionalProperties":true}; - -function validate48(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CompletionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.candidates === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "candidates"},message:"must have required property '"+"candidates"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.truncated === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.warnings !== undefined){ -let data0 = data.warnings; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/warnings",schemaPath:"#/properties/warnings/type",keyword:"type",params:{type: schema49.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err3 = {instancePath:instancePath+"/warnings/" + i0,schemaPath:"#/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -if(data.candidates !== undefined){ -let data2 = data.candidates; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err4 = {instancePath:instancePath+"/candidates",schemaPath:"#/properties/candidates/type",keyword:"type",params:{type: schema49.properties.candidates.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data2)){ -const len1 = data2.length; -for(let i1=0; i1<len1; i1++){ -let data3 = data2[i1]; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.text === undefined){ -const err5 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data3.description === undefined){ -const err6 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data3.text !== undefined){ -if(typeof data3.text !== "string"){ -const err7 = {instancePath:instancePath+"/candidates/" + i1+"/text",schemaPath:"#/properties/candidates/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data3.description !== undefined){ -if(typeof data3.description !== "string"){ -const err8 = {instancePath:instancePath+"/candidates/" + i1+"/description",schemaPath:"#/properties/candidates/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath:instancePath+"/candidates/" + i1,schemaPath:"#/properties/candidates/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err10 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate48.errors = vErrors; -return errors === 0; -} - -export const ComputerAppParams = validate49; -const schema50 = {"type":"object","properties":{"app":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ComputerAppParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ComputerAppParams","required":["app"],"additionalProperties":true}; - -function validate49(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ComputerAppParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.app === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "app"},message:"must have required property '"+"app"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.app !== undefined){ -if(typeof data.app !== "string"){ -const err1 = {instancePath:instancePath+"/app",schemaPath:"#/properties/app/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate49.errors = vErrors; -return errors === 0; -} - -export const ComputerStatusResult = validate50; -const schema51 = {"type":"object","properties":{"enabled":{"type":"boolean"},"default_deny":{"type":"boolean"},"allowed":{"type":["null","array"],"items":{"type":"string"}},"denied":{"type":["null","array"],"items":{"type":"string"}},"session_allowed":{"type":["null","array"],"items":{"type":"string"}},"session_denied":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ComputerStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ComputerStatusResult","required":["enabled","default_deny","allowed","denied","session_allowed","session_denied"],"additionalProperties":true}; - -function validate50(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ComputerStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.enabled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.default_deny === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_deny"},message:"must have required property '"+"default_deny"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.allowed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "allowed"},message:"must have required property '"+"allowed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.denied === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "denied"},message:"must have required property '"+"denied"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.session_allowed === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "session_allowed"},message:"must have required property '"+"session_allowed"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.session_denied === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "session_denied"},message:"must have required property '"+"session_denied"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err6 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.default_deny !== undefined){ -if(typeof data.default_deny !== "boolean"){ -const err7 = {instancePath:instancePath+"/default_deny",schemaPath:"#/properties/default_deny/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.allowed !== undefined){ -let data2 = data.allowed; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err8 = {instancePath:instancePath+"/allowed",schemaPath:"#/properties/allowed/type",keyword:"type",params:{type: schema51.properties.allowed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err9 = {instancePath:instancePath+"/allowed/" + i0,schemaPath:"#/properties/allowed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data.denied !== undefined){ -let data4 = data.denied; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err10 = {instancePath:instancePath+"/denied",schemaPath:"#/properties/denied/type",keyword:"type",params:{type: schema51.properties.denied.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data4[i1] !== "string"){ -const err11 = {instancePath:instancePath+"/denied/" + i1,schemaPath:"#/properties/denied/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -if(data.session_allowed !== undefined){ -let data6 = data.session_allowed; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err12 = {instancePath:instancePath+"/session_allowed",schemaPath:"#/properties/session_allowed/type",keyword:"type",params:{type: schema51.properties.session_allowed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(Array.isArray(data6)){ -const len2 = data6.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data6[i2] !== "string"){ -const err13 = {instancePath:instancePath+"/session_allowed/" + i2,schemaPath:"#/properties/session_allowed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -} -if(data.session_denied !== undefined){ -let data8 = data.session_denied; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err14 = {instancePath:instancePath+"/session_denied",schemaPath:"#/properties/session_denied/type",keyword:"type",params:{type: schema51.properties.session_denied.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(Array.isArray(data8)){ -const len3 = data8.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data8[i3] !== "string"){ -const err15 = {instancePath:instancePath+"/session_denied/" + i3,schemaPath:"#/properties/session_denied/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -} -else { -const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -validate50.errors = vErrors; -return errors === 0; -} - -export const ConfigurationUpdate = validate51; -const schema52 = {"type":"object","properties":{"default_execution_engine":{"type":["null","string"]},"disabled_providers":{"type":["null","array"],"items":{"type":"string"}},"remote_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"runtime_id":{"type":"string"},"connect_on_launch":{"type":"boolean"}},"required":["id","name","url","runtime_id","connect_on_launch"],"additionalProperties":true}},"import_claude":{"type":["null","boolean"]},"import_codex":{"type":["null","boolean"]},"brand_icons":{"type":["null","boolean"]},"revision":{"type":"string"},"default_model":{"type":["null","string"]},"default_provider":{"type":["null","string"]},"default_effort":{"type":["null","string"]},"default_permission_mode":{"type":["null","string"]},"compact_model":{"type":["null","string"]},"compact_provider":{"type":["null","string"]},"compact_percent":{"type":["null","integer"]},"goal_max_rounds":{"type":["null","integer"]},"max_retries":{"type":["null","integer"]}},"$id":"https://whip.dev/protocol/v6/ConfigurationUpdate","$schema":"http://json-schema.org/draft-07/schema#","title":"ConfigurationUpdate","required":["revision"],"additionalProperties":true}; - -function validate51(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ConfigurationUpdate" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.default_execution_engine !== undefined){ -let data0 = data.default_execution_engine; -if((data0 !== null) && (typeof data0 !== "string")){ -const err1 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: schema52.properties.default_execution_engine.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.disabled_providers !== undefined){ -let data1 = data.disabled_providers; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err2 = {instancePath:instancePath+"/disabled_providers",schemaPath:"#/properties/disabled_providers/type",keyword:"type",params:{type: schema52.properties.disabled_providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err3 = {instancePath:instancePath+"/disabled_providers/" + i0,schemaPath:"#/properties/disabled_providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -if(data.remote_hosts !== undefined){ -let data3 = data.remote_hosts; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err4 = {instancePath:instancePath+"/remote_hosts",schemaPath:"#/properties/remote_hosts/type",keyword:"type",params:{type: schema52.properties.remote_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data3)){ -const len1 = data3.length; -for(let i1=0; i1<len1; i1++){ -let data4 = data3[i1]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.id === undefined){ -const err5 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data4.name === undefined){ -const err6 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data4.url === undefined){ -const err7 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4.runtime_id === undefined){ -const err8 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.connect_on_launch === undefined){ -const err9 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "connect_on_launch"},message:"must have required property '"+"connect_on_launch"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.id !== undefined){ -if(typeof data4.id !== "string"){ -const err10 = {instancePath:instancePath+"/remote_hosts/" + i1+"/id",schemaPath:"#/properties/remote_hosts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err11 = {instancePath:instancePath+"/remote_hosts/" + i1+"/name",schemaPath:"#/properties/remote_hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data4.url !== undefined){ -if(typeof data4.url !== "string"){ -const err12 = {instancePath:instancePath+"/remote_hosts/" + i1+"/url",schemaPath:"#/properties/remote_hosts/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.runtime_id !== undefined){ -if(typeof data4.runtime_id !== "string"){ -const err13 = {instancePath:instancePath+"/remote_hosts/" + i1+"/runtime_id",schemaPath:"#/properties/remote_hosts/items/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data4.connect_on_launch !== undefined){ -if(typeof data4.connect_on_launch !== "boolean"){ -const err14 = {instancePath:instancePath+"/remote_hosts/" + i1+"/connect_on_launch",schemaPath:"#/properties/remote_hosts/items/properties/connect_on_launch/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data.import_claude !== undefined){ -let data10 = data.import_claude; -if((data10 !== null) && (typeof data10 !== "boolean")){ -const err16 = {instancePath:instancePath+"/import_claude",schemaPath:"#/properties/import_claude/type",keyword:"type",params:{type: schema52.properties.import_claude.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.import_codex !== undefined){ -let data11 = data.import_codex; -if((data11 !== null) && (typeof data11 !== "boolean")){ -const err17 = {instancePath:instancePath+"/import_codex",schemaPath:"#/properties/import_codex/type",keyword:"type",params:{type: schema52.properties.import_codex.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.brand_icons !== undefined){ -let data12 = data.brand_icons; -if((data12 !== null) && (typeof data12 !== "boolean")){ -const err18 = {instancePath:instancePath+"/brand_icons",schemaPath:"#/properties/brand_icons/type",keyword:"type",params:{type: schema52.properties.brand_icons.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err19 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.default_model !== undefined){ -let data14 = data.default_model; -if((data14 !== null) && (typeof data14 !== "string")){ -const err20 = {instancePath:instancePath+"/default_model",schemaPath:"#/properties/default_model/type",keyword:"type",params:{type: schema52.properties.default_model.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.default_provider !== undefined){ -let data15 = data.default_provider; -if((data15 !== null) && (typeof data15 !== "string")){ -const err21 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: schema52.properties.default_provider.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.default_effort !== undefined){ -let data16 = data.default_effort; -if((data16 !== null) && (typeof data16 !== "string")){ -const err22 = {instancePath:instancePath+"/default_effort",schemaPath:"#/properties/default_effort/type",keyword:"type",params:{type: schema52.properties.default_effort.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.default_permission_mode !== undefined){ -let data17 = data.default_permission_mode; -if((data17 !== null) && (typeof data17 !== "string")){ -const err23 = {instancePath:instancePath+"/default_permission_mode",schemaPath:"#/properties/default_permission_mode/type",keyword:"type",params:{type: schema52.properties.default_permission_mode.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.compact_model !== undefined){ -let data18 = data.compact_model; -if((data18 !== null) && (typeof data18 !== "string")){ -const err24 = {instancePath:instancePath+"/compact_model",schemaPath:"#/properties/compact_model/type",keyword:"type",params:{type: schema52.properties.compact_model.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.compact_provider !== undefined){ -let data19 = data.compact_provider; -if((data19 !== null) && (typeof data19 !== "string")){ -const err25 = {instancePath:instancePath+"/compact_provider",schemaPath:"#/properties/compact_provider/type",keyword:"type",params:{type: schema52.properties.compact_provider.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data.compact_percent !== undefined){ -let data20 = data.compact_percent; -if((data20 !== null) && (!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20))))){ -const err26 = {instancePath:instancePath+"/compact_percent",schemaPath:"#/properties/compact_percent/type",keyword:"type",params:{type: schema52.properties.compact_percent.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data.goal_max_rounds !== undefined){ -let data21 = data.goal_max_rounds; -if((data21 !== null) && (!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21))))){ -const err27 = {instancePath:instancePath+"/goal_max_rounds",schemaPath:"#/properties/goal_max_rounds/type",keyword:"type",params:{type: schema52.properties.goal_max_rounds.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data.max_retries !== undefined){ -let data22 = data.max_retries; -if((data22 !== null) && (!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22))))){ -const err28 = {instancePath:instancePath+"/max_retries",schemaPath:"#/properties/max_retries/type",keyword:"type",params:{type: schema52.properties.max_retries.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -validate51.errors = vErrors; -return errors === 0; -} - -export const ContentEventPayload = validate52; -const schema53 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true}},"required":["used","size","usage"],"additionalProperties":true},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"truncated":{"type":"boolean","const":true}},"$id":"https://whip.dev/protocol/v6/ContentEventPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentEventPayload","required":["content","truncated"],"additionalProperties":true}; - -function validate52(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentEventPayload" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.content === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.truncated === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.part_id !== undefined){ -if(typeof data.part_id !== "string"){ -const err2 = {instancePath:instancePath+"/part_id",schemaPath:"#/properties/part_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.display !== undefined){ -let data1 = data.display; -if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err3 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema53.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.target !== undefined){ -if(typeof data1.target !== "string"){ -const err4 = {instancePath:instancePath+"/display/target",schemaPath:"#/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.command !== undefined){ -if(typeof data1.command !== "string"){ -const err5 = {instancePath:instancePath+"/display/command",schemaPath:"#/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.query !== undefined){ -if(typeof data1.query !== "string"){ -const err6 = {instancePath:instancePath+"/display/query",schemaPath:"#/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.child_id !== undefined){ -if(typeof data1.child_id !== "string"){ -const err7 = {instancePath:instancePath+"/display/child_id",schemaPath:"#/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err8 = {instancePath:instancePath+"/display/label",schemaPath:"#/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data7 = data.accounting; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema53.properties.accounting.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.root_id === undefined){ -const err10 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7.agent_id === undefined){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7.scope === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7.revision === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.reported_cost_micros === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.estimated_cost_micros === undefined){ -const err15 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7.reported_cost_calls === undefined){ -const err16 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.estimated_cost_calls === undefined){ -const err17 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.unknown_cost_calls === undefined){ -const err18 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.reported_calls === undefined){ -const err19 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.estimated_calls === undefined){ -const err20 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data7.pending_calls === undefined){ -const err21 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err22 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err23 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data7.scope !== undefined){ -if(typeof data7.scope !== "string"){ -const err24 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data7.revision !== undefined){ -let data11 = data7.revision; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err25 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err26 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -else { -const err27 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data7.reported_cost_micros !== undefined){ -let data12 = data7.reported_cost_micros; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err28 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err29 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -else { -const err30 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data7.estimated_cost_micros !== undefined){ -let data13 = data7.estimated_cost_micros; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err31 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err32 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -else { -const err33 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data7.reported_cost_calls !== undefined){ -let data14 = data7.reported_cost_calls; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err34 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err35 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -else { -const err36 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data7.estimated_cost_calls !== undefined){ -let data15 = data7.estimated_cost_calls; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err37 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err38 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -else { -const err39 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data7.unknown_cost_calls !== undefined){ -let data16 = data7.unknown_cost_calls; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err40 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err41 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data7.reported_calls !== undefined){ -let data17 = data7.reported_calls; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err43 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err44 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data7.estimated_calls !== undefined){ -let data18 = data7.estimated_calls; -if(typeof data18 === "string"){ -if(!pattern0.test(data18)){ -const err46 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(!(formats0.validate(data18))){ -const err47 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -else { -const err48 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data7.pending_calls !== undefined){ -let data19 = data7.pending_calls; -if(typeof data19 === "string"){ -if(!pattern0.test(data19)){ -const err49 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(!(formats0.validate(data19))){ -const err50 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -else { -const err51 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -} -} -if(data.usage !== undefined){ -let data20 = data.usage; -if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err52 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema53.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.used === undefined){ -const err53 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data20.size === undefined){ -const err54 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data20.usage === undefined){ -const err55 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data20.used !== undefined){ -let data21 = data20.used; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err56 = {instancePath:instancePath+"/usage/used",schemaPath:"#/properties/usage/properties/used/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data20.size !== undefined){ -let data22 = data20.size; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err57 = {instancePath:instancePath+"/usage/size",schemaPath:"#/properties/usage/properties/size/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data20.usage !== undefined){ -let data23 = data20.usage; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt_tokens === undefined){ -const err58 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data23.completion_tokens === undefined){ -const err59 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data23.reported !== undefined){ -if(typeof data23.reported !== "boolean"){ -const err60 = {instancePath:instancePath+"/usage/usage/reported",schemaPath:"#/properties/usage/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data23.cost !== undefined){ -let data25 = data23.cost; -if((data25 !== null) && (!(typeof data25 == "number"))){ -const err61 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data23.prompt_tokens !== undefined){ -let data26 = data23.prompt_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err62 = {instancePath:instancePath+"/usage/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data23.completion_tokens !== undefined){ -let data27 = data23.completion_tokens; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err63 = {instancePath:instancePath+"/usage/usage/completion_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data23.prompt_tokens_details !== undefined){ -let data28 = data23.prompt_tokens_details; -if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err64 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data28 && typeof data28 == "object" && !Array.isArray(data28)){ -if(data28.cached_tokens === undefined){ -const err65 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data28.cached_tokens !== undefined){ -let data29 = data28.cached_tokens; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err66 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -} -} -if(data23.completion_tokens_details !== undefined){ -let data30 = data23.completion_tokens_details; -if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err67 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema53.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.reasoning_tokens === undefined){ -const err68 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data30.reasoning_tokens !== undefined){ -let data31 = data30.reasoning_tokens; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err69 = {instancePath:instancePath+"/usage/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -} -} -else { -const err70 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err71 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err72 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err73 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err74 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.host_status !== undefined){ -if(typeof data.host_status !== "string"){ -const err75 = {instancePath:instancePath+"/host_status",schemaPath:"#/properties/host_status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err76 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err77 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err78 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data.args !== undefined){ -if(typeof data.args !== "string"){ -const err79 = {instancePath:instancePath+"/args",schemaPath:"#/properties/args/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data.result !== undefined){ -if(typeof data.result !== "string"){ -const err80 = {instancePath:instancePath+"/result",schemaPath:"#/properties/result/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.content !== undefined){ -let data42 = data.content; -if(data42 && typeof data42 == "object" && !Array.isArray(data42)){ -if(data42.reference_id === undefined){ -const err81 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data42.digest === undefined){ -const err82 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data42.size === undefined){ -const err83 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data42.reference_id !== undefined){ -if(typeof data42.reference_id !== "string"){ -const err84 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data42.digest !== undefined){ -if(typeof data42.digest !== "string"){ -const err85 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data42.size !== undefined){ -let data45 = data42.size; -if(typeof data45 === "string"){ -if(!pattern0.test(data45)){ -const err86 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(!(formats0.validate(data45))){ -const err87 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -else { -const err88 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data42.media_type !== undefined){ -if(typeof data42.media_type !== "string"){ -const err89 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data42.source !== undefined){ -if(typeof data42.source !== "string"){ -const err90 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -} -else { -const err91 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data.truncated !== undefined){ -let data48 = data.truncated; -if(typeof data48 !== "boolean"){ -const err92 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -if(true !== data48){ -const err93 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/const",keyword:"const",params:{allowedValue: true},message:"must be equal to constant"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -} -else { -const err94 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -validate52.errors = vErrors; -return errors === 0; -} - -export const ContentHandle = validate53; -const schema54 = {"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ContentHandle","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentHandle","required":["reference_id","digest","size"],"additionalProperties":true}; - -function validate53(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentHandle" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.reference_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.digest === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.size === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.reference_id !== undefined){ -if(typeof data.reference_id !== "string"){ -const err3 = {instancePath:instancePath+"/reference_id",schemaPath:"#/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.digest !== undefined){ -if(typeof data.digest !== "string"){ -const err4 = {instancePath:instancePath+"/digest",schemaPath:"#/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.size !== undefined){ -let data2 = data.size; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err5 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err6 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.media_type !== undefined){ -if(typeof data.media_type !== "string"){ -const err8 = {instancePath:instancePath+"/media_type",schemaPath:"#/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err9 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate53.errors = vErrors; -return errors === 0; -} - -export const ContentReadParams = validate54; -const schema55 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"reference_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ContentReadParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentReadParams","required":["root_id","reference_id","offset","limit"],"additionalProperties":true}; - -function validate54(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentReadParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.reference_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.offset === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err5 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.reference_id !== undefined){ -if(typeof data.reference_id !== "string"){ -const err6 = {instancePath:instancePath+"/reference_id",schemaPath:"#/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.offset !== undefined){ -let data3 = data.offset; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err7 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err8 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -else { -const err9 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err10 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate54.errors = vErrors; -return errors === 0; -} - -export const ContentReadResult = validate55; -const schema56 = {"type":"object","properties":{"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/ContentReadResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ContentReadResult","required":["data","content"],"additionalProperties":true}; -const pattern52 = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", "u"); - -function validate55(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContentReadResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.data === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "data"},message:"must have required property '"+"data"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.content === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.data !== undefined){ -let data0 = data.data; -if((typeof data0 !== "string") && (data0 !== null)){ -const err2 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema56.properties.data.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern52.test(data0)){ -const err3 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -if(data.content !== undefined){ -let data1 = data.content; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.reference_id === undefined){ -const err4 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.digest === undefined){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.size === undefined){ -const err6 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.reference_id !== undefined){ -if(typeof data1.reference_id !== "string"){ -const err7 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.digest !== undefined){ -if(typeof data1.digest !== "string"){ -const err8 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.size !== undefined){ -let data4 = data1.size; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err9 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err10 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.media_type !== undefined){ -if(typeof data1.media_type !== "string"){ -const err12 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err13 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -validate55.errors = vErrors; -return errors === 0; -} - -export const ContextAuditResult = validate56; -const schema57 = {"type":"object","properties":{"working_directory":{"type":"string"},"rows":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"bytes":{"type":"integer"},"note":{"type":"string"}},"required":["label"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/ContextAuditResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ContextAuditResult","required":["working_directory","rows"],"additionalProperties":true}; - -function validate56(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ContextAuditResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.working_directory === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "working_directory"},message:"must have required property '"+"working_directory"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.rows === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.working_directory !== undefined){ -if(typeof data.working_directory !== "string"){ -const err2 = {instancePath:instancePath+"/working_directory",schemaPath:"#/properties/working_directory/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.rows !== undefined){ -let data1 = data.rows; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err3 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: schema57.properties.rows.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.label === undefined){ -const err4 = {instancePath:instancePath+"/rows/" + i0,schemaPath:"#/properties/rows/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data2.label !== undefined){ -if(typeof data2.label !== "string"){ -const err5 = {instancePath:instancePath+"/rows/" + i0+"/label",schemaPath:"#/properties/rows/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data2.bytes !== undefined){ -let data4 = data2.bytes; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err6 = {instancePath:instancePath+"/rows/" + i0+"/bytes",schemaPath:"#/properties/rows/items/properties/bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data2.note !== undefined){ -if(typeof data2.note !== "string"){ -const err7 = {instancePath:instancePath+"/rows/" + i0+"/note",schemaPath:"#/properties/rows/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath:instancePath+"/rows/" + i0,schemaPath:"#/properties/rows/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate56.errors = vErrors; -return errors === 0; -} - -export const CreateSessionParams = validate57; -const schema58 = {"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"kind":{"type":"string"},"cwd":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"permission_mode":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/CreateSessionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"CreateSessionParams","required":["kind","cwd","model","provider"],"additionalProperties":true}; - -function validate57(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/CreateSessionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.kind === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cwd === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.model === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.provider === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.execution_engine !== undefined){ -if(typeof data.execution_engine !== "string"){ -const err4 = {instancePath:instancePath+"/execution_engine",schemaPath:"#/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err5 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err6 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err7 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err8 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err9 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err10 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err11 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate57.errors = vErrors; -return errors === 0; -} - -export const DefinitionList = validate58; -const schema59 = {"type":"object","properties":{"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"},"built_in":{"type":"boolean"},"registered_by":{"type":"string"},"created_at":{"type":"string"}},"required":["id","revision","built_in","registered_by","created_at"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/DefinitionList","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionList","required":["items"],"additionalProperties":true}; - -function validate58(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items !== undefined){ -let data0 = data.items; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema59.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err2 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1.revision === undefined){ -const err3 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.built_in === undefined){ -const err4 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "built_in"},message:"must have required property '"+"built_in"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.registered_by === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "registered_by"},message:"must have required property '"+"registered_by"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.created_at === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err7 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.revision !== undefined){ -if(typeof data1.revision !== "string"){ -const err8 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.built_in !== undefined){ -if(typeof data1.built_in !== "boolean"){ -const err9 = {instancePath:instancePath+"/items/" + i0+"/built_in",schemaPath:"#/properties/items/items/properties/built_in/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.registered_by !== undefined){ -if(typeof data1.registered_by !== "string"){ -const err10 = {instancePath:instancePath+"/items/" + i0+"/registered_by",schemaPath:"#/properties/items/items/properties/registered_by/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.created_at !== undefined){ -if(typeof data1.created_at !== "string"){ -const err11 = {instancePath:instancePath+"/items/" + i0+"/created_at",schemaPath:"#/properties/items/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate58.errors = vErrors; -return errors === 0; -} - -export const DefinitionParams = validate59; -const schema60 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/DefinitionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionParams","required":["id"],"additionalProperties":true}; - -function validate59(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err1 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate59.errors = vErrors; -return errors === 0; -} - -export const DefinitionRecord = validate60; -const schema61 = {"type":"object","properties":{"definition":{"type":"object","properties":{"id":{"type":"string"},"instructions":{"type":"object","properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":true},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":true},"compaction":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"threshold":{"type":"number"}},"required":["model","provider","threshold"],"additionalProperties":true},"mcp":{"type":"object","properties":{"servers":{"type":["null","array"],"items":{"type":"string"}}},"required":["servers"],"additionalProperties":true},"tools":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"input_schema":true,"output_schema":true,"timeout_millis":{"type":"integer"}},"required":["name","description","input_schema","output_schema","timeout_millis"],"additionalProperties":true}},"output":true,"children":{"type":"object","additionalProperties":{"type":"object","properties":{"instructions":{"type":["null","object"],"properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":true},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":true},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"output":true},"required":["instructions","modules","capabilities","tools","model","budgets","report","output"],"additionalProperties":true}},"surface":{"type":"object","properties":{"auto_title":{"type":"boolean"},"goal_loop":{"type":"boolean"}},"required":["auto_title","goal_loop"],"additionalProperties":true},"hooks":{"type":["null","object"],"properties":{"before_tool":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true},"before_spawn":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true},"turn_start":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true}},"required":["before_tool","before_spawn","turn_start"],"additionalProperties":true}},"required":["id","instructions","modules","capabilities","model","compaction","mcp","tools","output","children","surface","hooks"],"additionalProperties":true},"revision":{"type":"string"},"built_in":{"type":"boolean"},"registered_by":{"type":"string"},"created_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/DefinitionRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRecord","required":["definition","revision","built_in","registered_by","created_at"],"additionalProperties":true}; - -function validate60(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.built_in === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "built_in"},message:"must have required property '"+"built_in"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.registered_by === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "registered_by"},message:"must have required property '"+"registered_by"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.created_at === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.definition !== undefined){ -let data0 = data.definition; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err5 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.instructions === undefined){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.modules === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.capabilities === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.model === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.compaction === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "compaction"},message:"must have required property '"+"compaction"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.mcp === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.tools === undefined){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.output === undefined){ -const err13 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.children === undefined){ -const err14 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "children"},message:"must have required property '"+"children"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.surface === undefined){ -const err15 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.hooks === undefined){ -const err16 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "hooks"},message:"must have required property '"+"hooks"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err17 = {instancePath:instancePath+"/definition/id",schemaPath:"#/properties/definition/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data0.instructions !== undefined){ -let data2 = data0.instructions; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.persona === undefined){ -const err18 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2.rules === undefined){ -const err19 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2.project_files === undefined){ -const err20 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.skill_discovery === undefined){ -const err21 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data2.standing_instructions === undefined){ -const err22 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data2.persona !== undefined){ -if(typeof data2.persona !== "string"){ -const err23 = {instancePath:instancePath+"/definition/instructions/persona",schemaPath:"#/properties/definition/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.rules !== undefined){ -if(typeof data2.rules !== "string"){ -const err24 = {instancePath:instancePath+"/definition/instructions/rules",schemaPath:"#/properties/definition/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.project_files !== undefined){ -let data5 = data2.project_files; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err25 = {instancePath:instancePath+"/definition/instructions/project_files",schemaPath:"#/properties/definition/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema61.properties.definition.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data5[i0] !== "string"){ -const err26 = {instancePath:instancePath+"/definition/instructions/project_files/" + i0,schemaPath:"#/properties/definition/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -} -if(data2.skill_discovery !== undefined){ -if(typeof data2.skill_discovery !== "boolean"){ -const err27 = {instancePath:instancePath+"/definition/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.standing_instructions !== undefined){ -if(typeof data2.standing_instructions !== "boolean"){ -const err28 = {instancePath:instancePath+"/definition/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data0.modules !== undefined){ -let data9 = data0.modules; -if((data9 !== null) && (!(Array.isArray(data9)))){ -const err30 = {instancePath:instancePath+"/definition/modules",schemaPath:"#/properties/definition/properties/modules/type",keyword:"type",params:{type: schema61.properties.definition.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(Array.isArray(data9)){ -const len1 = data9.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data9[i1] !== "string"){ -const err31 = {instancePath:instancePath+"/definition/modules/" + i1,schemaPath:"#/properties/definition/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -} -if(data0.capabilities !== undefined){ -let data11 = data0.capabilities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err32 = {instancePath:instancePath+"/definition/capabilities",schemaPath:"#/properties/definition/properties/capabilities/type",keyword:"type",params:{type: schema61.properties.definition.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err33 = {instancePath:instancePath+"/definition/capabilities/" + i2,schemaPath:"#/properties/definition/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -if(data0.model !== undefined){ -let data13 = data0.model; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.model === undefined){ -const err34 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data13.provider === undefined){ -const err35 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data13.effort === undefined){ -const err36 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data13.model !== undefined){ -if(typeof data13.model !== "string"){ -const err37 = {instancePath:instancePath+"/definition/model/model",schemaPath:"#/properties/definition/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data13.provider !== undefined){ -if(typeof data13.provider !== "string"){ -const err38 = {instancePath:instancePath+"/definition/model/provider",schemaPath:"#/properties/definition/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data13.effort !== undefined){ -if(typeof data13.effort !== "string"){ -const err39 = {instancePath:instancePath+"/definition/model/effort",schemaPath:"#/properties/definition/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -} -else { -const err40 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data0.compaction !== undefined){ -let data17 = data0.compaction; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.model === undefined){ -const err41 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data17.provider === undefined){ -const err42 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data17.threshold === undefined){ -const err43 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "threshold"},message:"must have required property '"+"threshold"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data17.model !== undefined){ -if(typeof data17.model !== "string"){ -const err44 = {instancePath:instancePath+"/definition/compaction/model",schemaPath:"#/properties/definition/properties/compaction/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data17.provider !== undefined){ -if(typeof data17.provider !== "string"){ -const err45 = {instancePath:instancePath+"/definition/compaction/provider",schemaPath:"#/properties/definition/properties/compaction/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data17.threshold !== undefined){ -if(!(typeof data17.threshold == "number")){ -const err46 = {instancePath:instancePath+"/definition/compaction/threshold",schemaPath:"#/properties/definition/properties/compaction/properties/threshold/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -else { -const err47 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data0.mcp !== undefined){ -let data21 = data0.mcp; -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.servers === undefined){ -const err48 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data21.servers !== undefined){ -let data22 = data21.servers; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err49 = {instancePath:instancePath+"/definition/mcp/servers",schemaPath:"#/properties/definition/properties/mcp/properties/servers/type",keyword:"type",params:{type: schema61.properties.definition.properties.mcp.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(Array.isArray(data22)){ -const len3 = data22.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data22[i3] !== "string"){ -const err50 = {instancePath:instancePath+"/definition/mcp/servers/" + i3,schemaPath:"#/properties/definition/properties/mcp/properties/servers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -} -} -} -else { -const err51 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data24 = data0.tools; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err52 = {instancePath:instancePath+"/definition/tools",schemaPath:"#/properties/definition/properties/tools/type",keyword:"type",params:{type: schema61.properties.definition.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(Array.isArray(data24)){ -const len4 = data24.length; -for(let i4=0; i4<len4; i4++){ -let data25 = data24[i4]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.name === undefined){ -const err53 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data25.description === undefined){ -const err54 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data25.input_schema === undefined){ -const err55 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "input_schema"},message:"must have required property '"+"input_schema"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data25.output_schema === undefined){ -const err56 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "output_schema"},message:"must have required property '"+"output_schema"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data25.timeout_millis === undefined){ -const err57 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data25.name !== undefined){ -if(typeof data25.name !== "string"){ -const err58 = {instancePath:instancePath+"/definition/tools/" + i4+"/name",schemaPath:"#/properties/definition/properties/tools/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data25.description !== undefined){ -if(typeof data25.description !== "string"){ -const err59 = {instancePath:instancePath+"/definition/tools/" + i4+"/description",schemaPath:"#/properties/definition/properties/tools/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data25.timeout_millis !== undefined){ -let data28 = data25.timeout_millis; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err60 = {instancePath:instancePath+"/definition/tools/" + i4+"/timeout_millis",schemaPath:"#/properties/definition/properties/tools/items/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -} -else { -const err61 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -} -} -if(data0.children !== undefined){ -let data29 = data0.children; -if(data29 && typeof data29 == "object" && !Array.isArray(data29)){ -for(const key0 in data29){ -let data30 = data29[key0]; -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.instructions === undefined){ -const err62 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data30.modules === undefined){ -const err63 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data30.capabilities === undefined){ -const err64 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data30.tools === undefined){ -const err65 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data30.model === undefined){ -const err66 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(data30.budgets === undefined){ -const err67 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data30.report === undefined){ -const err68 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data30.output === undefined){ -const err69 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data30.instructions !== undefined){ -let data31 = data30.instructions; -if((data31 !== null) && (!(data31 && typeof data31 == "object" && !Array.isArray(data31)))){ -const err70 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.instructions.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -if(data31.persona === undefined){ -const err71 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data31.rules === undefined){ -const err72 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(data31.project_files === undefined){ -const err73 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -if(data31.skill_discovery === undefined){ -const err74 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(data31.standing_instructions === undefined){ -const err75 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(data31.persona !== undefined){ -if(typeof data31.persona !== "string"){ -const err76 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/persona",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data31.rules !== undefined){ -if(typeof data31.rules !== "string"){ -const err77 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/rules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data31.project_files !== undefined){ -let data34 = data31.project_files; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err78 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(Array.isArray(data34)){ -const len5 = data34.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data34[i5] !== "string"){ -const err79 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files/" + i5,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -} -} -if(data31.skill_discovery !== undefined){ -if(typeof data31.skill_discovery !== "boolean"){ -const err80 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data31.standing_instructions !== undefined){ -if(typeof data31.standing_instructions !== "boolean"){ -const err81 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -} -} -if(data30.modules !== undefined){ -let data38 = data30.modules; -if((data38 !== null) && (!(Array.isArray(data38)))){ -const err82 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(Array.isArray(data38)){ -const len6 = data38.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data38[i6] !== "string"){ -const err83 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules/" + i6,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -} -} -if(data30.capabilities !== undefined){ -let data40 = data30.capabilities; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err84 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(Array.isArray(data40)){ -const len7 = data40.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data40[i7] !== "string"){ -const err85 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities/" + i7,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -} -} -if(data30.tools !== undefined){ -let data42 = data30.tools; -if((data42 !== null) && (!(Array.isArray(data42)))){ -const err86 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/type",keyword:"type",params:{type: schema61.properties.definition.properties.children.additionalProperties.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(Array.isArray(data42)){ -const len8 = data42.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data42[i8] !== "string"){ -const err87 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools/" + i8,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -} -} -if(data30.model !== undefined){ -let data44 = data30.model; -if(data44 && typeof data44 == "object" && !Array.isArray(data44)){ -if(data44.model === undefined){ -const err88 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(data44.provider === undefined){ -const err89 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(data44.effort === undefined){ -const err90 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -if(data44.model !== undefined){ -if(typeof data44.model !== "string"){ -const err91 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data44.provider !== undefined){ -if(typeof data44.provider !== "string"){ -const err92 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/provider",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data44.effort !== undefined){ -if(typeof data44.effort !== "string"){ -const err93 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/effort",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -} -else { -const err94 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data30.budgets !== undefined){ -let data48 = data30.budgets; -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -for(const key1 in data48){ -let data49 = data48[key1]; -if(!((typeof data49 == "number") && (!(data49 % 1) && !isNaN(data49)))){ -const err95 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -} -else { -const err96 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data30.report !== undefined){ -if(typeof data30.report !== "string"){ -const err97 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/report",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -else { -const err98 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -else { -const err99 = {instancePath:instancePath+"/definition/children",schemaPath:"#/properties/definition/properties/children/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data0.surface !== undefined){ -let data51 = data0.surface; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.auto_title === undefined){ -const err100 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "auto_title"},message:"must have required property '"+"auto_title"+"'"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -if(data51.goal_loop === undefined){ -const err101 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "goal_loop"},message:"must have required property '"+"goal_loop"+"'"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(data51.auto_title !== undefined){ -if(typeof data51.auto_title !== "boolean"){ -const err102 = {instancePath:instancePath+"/definition/surface/auto_title",schemaPath:"#/properties/definition/properties/surface/properties/auto_title/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -if(data51.goal_loop !== undefined){ -if(typeof data51.goal_loop !== "boolean"){ -const err103 = {instancePath:instancePath+"/definition/surface/goal_loop",schemaPath:"#/properties/definition/properties/surface/properties/goal_loop/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -} -else { -const err104 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data0.hooks !== undefined){ -let data54 = data0.hooks; -if((data54 !== null) && (!(data54 && typeof data54 == "object" && !Array.isArray(data54)))){ -const err105 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.before_tool === undefined){ -const err106 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_tool"},message:"must have required property '"+"before_tool"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(data54.before_spawn === undefined){ -const err107 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_spawn"},message:"must have required property '"+"before_spawn"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -if(data54.turn_start === undefined){ -const err108 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "turn_start"},message:"must have required property '"+"turn_start"+"'"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -if(data54.before_tool !== undefined){ -let data55 = data54.before_tool; -if((data55 !== null) && (!(data55 && typeof data55 == "object" && !Array.isArray(data55)))){ -const err109 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_tool.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -if(data55 && typeof data55 == "object" && !Array.isArray(data55)){ -if(data55.operations === undefined){ -const err110 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -if(data55.optional === undefined){ -const err111 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -if(data55.timeout_millis === undefined){ -const err112 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -if(data55.operations !== undefined){ -let data56 = data55.operations; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err113 = {instancePath:instancePath+"/definition/hooks/before_tool/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_tool.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(Array.isArray(data56)){ -const len9 = data56.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data56[i9] !== "string"){ -const err114 = {instancePath:instancePath+"/definition/hooks/before_tool/operations/" + i9,schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -} -} -if(data55.optional !== undefined){ -if(typeof data55.optional !== "boolean"){ -const err115 = {instancePath:instancePath+"/definition/hooks/before_tool/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data55.timeout_millis !== undefined){ -let data59 = data55.timeout_millis; -if(!((typeof data59 == "number") && (!(data59 % 1) && !isNaN(data59)))){ -const err116 = {instancePath:instancePath+"/definition/hooks/before_tool/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -} -} -if(data54.before_spawn !== undefined){ -let data60 = data54.before_spawn; -if((data60 !== null) && (!(data60 && typeof data60 == "object" && !Array.isArray(data60)))){ -const err117 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(data60 && typeof data60 == "object" && !Array.isArray(data60)){ -if(data60.operations === undefined){ -const err118 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data60.optional === undefined){ -const err119 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data60.timeout_millis === undefined){ -const err120 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(data60.operations !== undefined){ -let data61 = data60.operations; -if((data61 !== null) && (!(Array.isArray(data61)))){ -const err121 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.before_spawn.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(Array.isArray(data61)){ -const len10 = data61.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data61[i10] !== "string"){ -const err122 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations/" + i10,schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -} -} -if(data60.optional !== undefined){ -if(typeof data60.optional !== "boolean"){ -const err123 = {instancePath:instancePath+"/definition/hooks/before_spawn/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data60.timeout_millis !== undefined){ -let data64 = data60.timeout_millis; -if(!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64)))){ -const err124 = {instancePath:instancePath+"/definition/hooks/before_spawn/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -} -} -if(data54.turn_start !== undefined){ -let data65 = data54.turn_start; -if((data65 !== null) && (!(data65 && typeof data65 == "object" && !Array.isArray(data65)))){ -const err125 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.turn_start.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.operations === undefined){ -const err126 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -if(data65.optional === undefined){ -const err127 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -if(data65.timeout_millis === undefined){ -const err128 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -if(data65.operations !== undefined){ -let data66 = data65.operations; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err129 = {instancePath:instancePath+"/definition/hooks/turn_start/operations",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/type",keyword:"type",params:{type: schema61.properties.definition.properties.hooks.properties.turn_start.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -if(Array.isArray(data66)){ -const len11 = data66.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data66[i11] !== "string"){ -const err130 = {instancePath:instancePath+"/definition/hooks/turn_start/operations/" + i11,schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -} -} -if(data65.optional !== undefined){ -if(typeof data65.optional !== "boolean"){ -const err131 = {instancePath:instancePath+"/definition/hooks/turn_start/optional",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -if(data65.timeout_millis !== undefined){ -let data69 = data65.timeout_millis; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err132 = {instancePath:instancePath+"/definition/hooks/turn_start/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -} -} -} -} -} -else { -const err133 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err134 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data.built_in !== undefined){ -if(typeof data.built_in !== "boolean"){ -const err135 = {instancePath:instancePath+"/built_in",schemaPath:"#/properties/built_in/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -if(data.registered_by !== undefined){ -if(typeof data.registered_by !== "string"){ -const err136 = {instancePath:instancePath+"/registered_by",schemaPath:"#/properties/registered_by/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err137 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -} -else { -const err138 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -validate60.errors = vErrors; -return errors === 0; -} - -export const DefinitionRegisterParams = validate61; -const schema62 = {"type":"object","properties":{"definition":{"type":"object","properties":{"id":{"type":"string"},"instructions":{"type":"object","properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":true},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":true},"compaction":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"threshold":{"type":"number"}},"required":["model","provider","threshold"],"additionalProperties":true},"mcp":{"type":"object","properties":{"servers":{"type":["null","array"],"items":{"type":"string"}}},"required":["servers"],"additionalProperties":true},"tools":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"input_schema":true,"output_schema":true,"timeout_millis":{"type":"integer"}},"required":["name","description","input_schema","output_schema","timeout_millis"],"additionalProperties":true}},"output":true,"children":{"type":"object","additionalProperties":{"type":"object","properties":{"instructions":{"type":["null","object"],"properties":{"persona":{"type":"string"},"rules":{"type":"string"},"project_files":{"type":["null","array"],"items":{"type":"string"}},"skill_discovery":{"type":"boolean"},"standing_instructions":{"type":"boolean"}},"required":["persona","rules","project_files","skill_discovery","standing_instructions"],"additionalProperties":true},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"model":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"}},"required":["model","provider","effort"],"additionalProperties":true},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"output":true},"required":["instructions","modules","capabilities","tools","model","budgets","report","output"],"additionalProperties":true}},"surface":{"type":"object","properties":{"auto_title":{"type":"boolean"},"goal_loop":{"type":"boolean"}},"required":["auto_title","goal_loop"],"additionalProperties":true},"hooks":{"type":["null","object"],"properties":{"before_tool":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true},"before_spawn":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true},"turn_start":{"type":["null","object"],"properties":{"operations":{"type":["null","array"],"items":{"type":"string"}},"optional":{"type":"boolean"},"timeout_millis":{"type":"integer"}},"required":["operations","optional","timeout_millis"],"additionalProperties":true}},"required":["before_tool","before_spawn","turn_start"],"additionalProperties":true}},"required":["id","instructions","modules","capabilities","model","compaction","mcp","tools","output","children","surface","hooks"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/DefinitionRegisterParams","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRegisterParams","required":["definition"],"additionalProperties":true}; - -function validate61(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRegisterParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.definition !== undefined){ -let data0 = data.definition; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err1 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.instructions === undefined){ -const err2 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.modules === undefined){ -const err3 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.capabilities === undefined){ -const err4 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.model === undefined){ -const err5 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.compaction === undefined){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "compaction"},message:"must have required property '"+"compaction"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.mcp === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.tools === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.output === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.children === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "children"},message:"must have required property '"+"children"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.surface === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.hooks === undefined){ -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "hooks"},message:"must have required property '"+"hooks"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err13 = {instancePath:instancePath+"/definition/id",schemaPath:"#/properties/definition/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data0.instructions !== undefined){ -let data2 = data0.instructions; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.persona === undefined){ -const err14 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.rules === undefined){ -const err15 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.project_files === undefined){ -const err16 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.skill_discovery === undefined){ -const err17 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data2.standing_instructions === undefined){ -const err18 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2.persona !== undefined){ -if(typeof data2.persona !== "string"){ -const err19 = {instancePath:instancePath+"/definition/instructions/persona",schemaPath:"#/properties/definition/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data2.rules !== undefined){ -if(typeof data2.rules !== "string"){ -const err20 = {instancePath:instancePath+"/definition/instructions/rules",schemaPath:"#/properties/definition/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data2.project_files !== undefined){ -let data5 = data2.project_files; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err21 = {instancePath:instancePath+"/definition/instructions/project_files",schemaPath:"#/properties/definition/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema62.properties.definition.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data5[i0] !== "string"){ -const err22 = {instancePath:instancePath+"/definition/instructions/project_files/" + i0,schemaPath:"#/properties/definition/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -} -if(data2.skill_discovery !== undefined){ -if(typeof data2.skill_discovery !== "boolean"){ -const err23 = {instancePath:instancePath+"/definition/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.standing_instructions !== undefined){ -if(typeof data2.standing_instructions !== "boolean"){ -const err24 = {instancePath:instancePath+"/definition/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath:instancePath+"/definition/instructions",schemaPath:"#/properties/definition/properties/instructions/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data0.modules !== undefined){ -let data9 = data0.modules; -if((data9 !== null) && (!(Array.isArray(data9)))){ -const err26 = {instancePath:instancePath+"/definition/modules",schemaPath:"#/properties/definition/properties/modules/type",keyword:"type",params:{type: schema62.properties.definition.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data9)){ -const len1 = data9.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data9[i1] !== "string"){ -const err27 = {instancePath:instancePath+"/definition/modules/" + i1,schemaPath:"#/properties/definition/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -if(data0.capabilities !== undefined){ -let data11 = data0.capabilities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err28 = {instancePath:instancePath+"/definition/capabilities",schemaPath:"#/properties/definition/properties/capabilities/type",keyword:"type",params:{type: schema62.properties.definition.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err29 = {instancePath:instancePath+"/definition/capabilities/" + i2,schemaPath:"#/properties/definition/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -} -if(data0.model !== undefined){ -let data13 = data0.model; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.model === undefined){ -const err30 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data13.provider === undefined){ -const err31 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data13.effort === undefined){ -const err32 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data13.model !== undefined){ -if(typeof data13.model !== "string"){ -const err33 = {instancePath:instancePath+"/definition/model/model",schemaPath:"#/properties/definition/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data13.provider !== undefined){ -if(typeof data13.provider !== "string"){ -const err34 = {instancePath:instancePath+"/definition/model/provider",schemaPath:"#/properties/definition/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data13.effort !== undefined){ -if(typeof data13.effort !== "string"){ -const err35 = {instancePath:instancePath+"/definition/model/effort",schemaPath:"#/properties/definition/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -else { -const err36 = {instancePath:instancePath+"/definition/model",schemaPath:"#/properties/definition/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data0.compaction !== undefined){ -let data17 = data0.compaction; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.model === undefined){ -const err37 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data17.provider === undefined){ -const err38 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data17.threshold === undefined){ -const err39 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/required",keyword:"required",params:{missingProperty: "threshold"},message:"must have required property '"+"threshold"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data17.model !== undefined){ -if(typeof data17.model !== "string"){ -const err40 = {instancePath:instancePath+"/definition/compaction/model",schemaPath:"#/properties/definition/properties/compaction/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data17.provider !== undefined){ -if(typeof data17.provider !== "string"){ -const err41 = {instancePath:instancePath+"/definition/compaction/provider",schemaPath:"#/properties/definition/properties/compaction/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data17.threshold !== undefined){ -if(!(typeof data17.threshold == "number")){ -const err42 = {instancePath:instancePath+"/definition/compaction/threshold",schemaPath:"#/properties/definition/properties/compaction/properties/threshold/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -else { -const err43 = {instancePath:instancePath+"/definition/compaction",schemaPath:"#/properties/definition/properties/compaction/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data0.mcp !== undefined){ -let data21 = data0.mcp; -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.servers === undefined){ -const err44 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data21.servers !== undefined){ -let data22 = data21.servers; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err45 = {instancePath:instancePath+"/definition/mcp/servers",schemaPath:"#/properties/definition/properties/mcp/properties/servers/type",keyword:"type",params:{type: schema62.properties.definition.properties.mcp.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(Array.isArray(data22)){ -const len3 = data22.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data22[i3] !== "string"){ -const err46 = {instancePath:instancePath+"/definition/mcp/servers/" + i3,schemaPath:"#/properties/definition/properties/mcp/properties/servers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -} -} -else { -const err47 = {instancePath:instancePath+"/definition/mcp",schemaPath:"#/properties/definition/properties/mcp/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data24 = data0.tools; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err48 = {instancePath:instancePath+"/definition/tools",schemaPath:"#/properties/definition/properties/tools/type",keyword:"type",params:{type: schema62.properties.definition.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(Array.isArray(data24)){ -const len4 = data24.length; -for(let i4=0; i4<len4; i4++){ -let data25 = data24[i4]; -if(data25 && typeof data25 == "object" && !Array.isArray(data25)){ -if(data25.name === undefined){ -const err49 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data25.description === undefined){ -const err50 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data25.input_schema === undefined){ -const err51 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "input_schema"},message:"must have required property '"+"input_schema"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data25.output_schema === undefined){ -const err52 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "output_schema"},message:"must have required property '"+"output_schema"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data25.timeout_millis === undefined){ -const err53 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data25.name !== undefined){ -if(typeof data25.name !== "string"){ -const err54 = {instancePath:instancePath+"/definition/tools/" + i4+"/name",schemaPath:"#/properties/definition/properties/tools/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data25.description !== undefined){ -if(typeof data25.description !== "string"){ -const err55 = {instancePath:instancePath+"/definition/tools/" + i4+"/description",schemaPath:"#/properties/definition/properties/tools/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data25.timeout_millis !== undefined){ -let data28 = data25.timeout_millis; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err56 = {instancePath:instancePath+"/definition/tools/" + i4+"/timeout_millis",schemaPath:"#/properties/definition/properties/tools/items/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -} -else { -const err57 = {instancePath:instancePath+"/definition/tools/" + i4,schemaPath:"#/properties/definition/properties/tools/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -} -} -if(data0.children !== undefined){ -let data29 = data0.children; -if(data29 && typeof data29 == "object" && !Array.isArray(data29)){ -for(const key0 in data29){ -let data30 = data29[key0]; -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.instructions === undefined){ -const err58 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "instructions"},message:"must have required property '"+"instructions"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data30.modules === undefined){ -const err59 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data30.capabilities === undefined){ -const err60 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data30.tools === undefined){ -const err61 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(data30.model === undefined){ -const err62 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data30.budgets === undefined){ -const err63 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data30.report === undefined){ -const err64 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(data30.output === undefined){ -const err65 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/required",keyword:"required",params:{missingProperty: "output"},message:"must have required property '"+"output"+"'"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data30.instructions !== undefined){ -let data31 = data30.instructions; -if((data31 !== null) && (!(data31 && typeof data31 == "object" && !Array.isArray(data31)))){ -const err66 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.instructions.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -if(data31.persona === undefined){ -const err67 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "persona"},message:"must have required property '"+"persona"+"'"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -if(data31.rules === undefined){ -const err68 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data31.project_files === undefined){ -const err69 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "project_files"},message:"must have required property '"+"project_files"+"'"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data31.skill_discovery === undefined){ -const err70 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "skill_discovery"},message:"must have required property '"+"skill_discovery"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data31.standing_instructions === undefined){ -const err71 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/required",keyword:"required",params:{missingProperty: "standing_instructions"},message:"must have required property '"+"standing_instructions"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data31.persona !== undefined){ -if(typeof data31.persona !== "string"){ -const err72 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/persona",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/persona/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data31.rules !== undefined){ -if(typeof data31.rules !== "string"){ -const err73 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/rules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/rules/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data31.project_files !== undefined){ -let data34 = data31.project_files; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err74 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.instructions.properties.project_files.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(Array.isArray(data34)){ -const len5 = data34.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data34[i5] !== "string"){ -const err75 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/project_files/" + i5,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/project_files/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -} -} -if(data31.skill_discovery !== undefined){ -if(typeof data31.skill_discovery !== "boolean"){ -const err76 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/skill_discovery",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/skill_discovery/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data31.standing_instructions !== undefined){ -if(typeof data31.standing_instructions !== "boolean"){ -const err77 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/instructions/standing_instructions",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/instructions/properties/standing_instructions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -} -} -if(data30.modules !== undefined){ -let data38 = data30.modules; -if((data38 !== null) && (!(Array.isArray(data38)))){ -const err78 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(Array.isArray(data38)){ -const len6 = data38.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data38[i6] !== "string"){ -const err79 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/modules/" + i6,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -} -} -if(data30.capabilities !== undefined){ -let data40 = data30.capabilities; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err80 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(Array.isArray(data40)){ -const len7 = data40.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data40[i7] !== "string"){ -const err81 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/capabilities/" + i7,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -} -} -if(data30.tools !== undefined){ -let data42 = data30.tools; -if((data42 !== null) && (!(Array.isArray(data42)))){ -const err82 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/type",keyword:"type",params:{type: schema62.properties.definition.properties.children.additionalProperties.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(Array.isArray(data42)){ -const len8 = data42.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data42[i8] !== "string"){ -const err83 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/tools/" + i8,schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -} -} -if(data30.model !== undefined){ -let data44 = data30.model; -if(data44 && typeof data44 == "object" && !Array.isArray(data44)){ -if(data44.model === undefined){ -const err84 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data44.provider === undefined){ -const err85 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data44.effort === undefined){ -const err86 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data44.model !== undefined){ -if(typeof data44.model !== "string"){ -const err87 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data44.provider !== undefined){ -if(typeof data44.provider !== "string"){ -const err88 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/provider",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data44.effort !== undefined){ -if(typeof data44.effort !== "string"){ -const err89 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model/effort",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -} -else { -const err90 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/model",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/model/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data30.budgets !== undefined){ -let data48 = data30.budgets; -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -for(const key1 in data48){ -let data49 = data48[key1]; -if(!((typeof data49 == "number") && (!(data49 % 1) && !isNaN(data49)))){ -const err91 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -} -else { -const err92 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/budgets",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data30.report !== undefined){ -if(typeof data30.report !== "string"){ -const err93 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/report",schemaPath:"#/properties/definition/properties/children/additionalProperties/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -} -else { -const err94 = {instancePath:instancePath+"/definition/children/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/definition/properties/children/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -} -else { -const err95 = {instancePath:instancePath+"/definition/children",schemaPath:"#/properties/definition/properties/children/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data0.surface !== undefined){ -let data51 = data0.surface; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.auto_title === undefined){ -const err96 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "auto_title"},message:"must have required property '"+"auto_title"+"'"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -if(data51.goal_loop === undefined){ -const err97 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/required",keyword:"required",params:{missingProperty: "goal_loop"},message:"must have required property '"+"goal_loop"+"'"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -if(data51.auto_title !== undefined){ -if(typeof data51.auto_title !== "boolean"){ -const err98 = {instancePath:instancePath+"/definition/surface/auto_title",schemaPath:"#/properties/definition/properties/surface/properties/auto_title/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data51.goal_loop !== undefined){ -if(typeof data51.goal_loop !== "boolean"){ -const err99 = {instancePath:instancePath+"/definition/surface/goal_loop",schemaPath:"#/properties/definition/properties/surface/properties/goal_loop/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -} -else { -const err100 = {instancePath:instancePath+"/definition/surface",schemaPath:"#/properties/definition/properties/surface/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data0.hooks !== undefined){ -let data54 = data0.hooks; -if((data54 !== null) && (!(data54 && typeof data54 == "object" && !Array.isArray(data54)))){ -const err101 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.before_tool === undefined){ -const err102 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_tool"},message:"must have required property '"+"before_tool"+"'"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(data54.before_spawn === undefined){ -const err103 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "before_spawn"},message:"must have required property '"+"before_spawn"+"'"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -if(data54.turn_start === undefined){ -const err104 = {instancePath:instancePath+"/definition/hooks",schemaPath:"#/properties/definition/properties/hooks/required",keyword:"required",params:{missingProperty: "turn_start"},message:"must have required property '"+"turn_start"+"'"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -if(data54.before_tool !== undefined){ -let data55 = data54.before_tool; -if((data55 !== null) && (!(data55 && typeof data55 == "object" && !Array.isArray(data55)))){ -const err105 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_tool.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(data55 && typeof data55 == "object" && !Array.isArray(data55)){ -if(data55.operations === undefined){ -const err106 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -if(data55.optional === undefined){ -const err107 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -if(data55.timeout_millis === undefined){ -const err108 = {instancePath:instancePath+"/definition/hooks/before_tool",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -if(data55.operations !== undefined){ -let data56 = data55.operations; -if((data56 !== null) && (!(Array.isArray(data56)))){ -const err109 = {instancePath:instancePath+"/definition/hooks/before_tool/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_tool.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -if(Array.isArray(data56)){ -const len9 = data56.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data56[i9] !== "string"){ -const err110 = {instancePath:instancePath+"/definition/hooks/before_tool/operations/" + i9,schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -} -} -if(data55.optional !== undefined){ -if(typeof data55.optional !== "boolean"){ -const err111 = {instancePath:instancePath+"/definition/hooks/before_tool/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data55.timeout_millis !== undefined){ -let data59 = data55.timeout_millis; -if(!((typeof data59 == "number") && (!(data59 % 1) && !isNaN(data59)))){ -const err112 = {instancePath:instancePath+"/definition/hooks/before_tool/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_tool/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -} -} -if(data54.before_spawn !== undefined){ -let data60 = data54.before_spawn; -if((data60 !== null) && (!(data60 && typeof data60 == "object" && !Array.isArray(data60)))){ -const err113 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(data60 && typeof data60 == "object" && !Array.isArray(data60)){ -if(data60.operations === undefined){ -const err114 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data60.optional === undefined){ -const err115 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -if(data60.timeout_millis === undefined){ -const err116 = {instancePath:instancePath+"/definition/hooks/before_spawn",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -if(data60.operations !== undefined){ -let data61 = data60.operations; -if((data61 !== null) && (!(Array.isArray(data61)))){ -const err117 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.before_spawn.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(Array.isArray(data61)){ -const len10 = data61.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data61[i10] !== "string"){ -const err118 = {instancePath:instancePath+"/definition/hooks/before_spawn/operations/" + i10,schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -} -} -if(data60.optional !== undefined){ -if(typeof data60.optional !== "boolean"){ -const err119 = {instancePath:instancePath+"/definition/hooks/before_spawn/optional",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -if(data60.timeout_millis !== undefined){ -let data64 = data60.timeout_millis; -if(!((typeof data64 == "number") && (!(data64 % 1) && !isNaN(data64)))){ -const err120 = {instancePath:instancePath+"/definition/hooks/before_spawn/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/before_spawn/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -} -} -if(data54.turn_start !== undefined){ -let data65 = data54.turn_start; -if((data65 !== null) && (!(data65 && typeof data65 == "object" && !Array.isArray(data65)))){ -const err121 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.turn_start.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.operations === undefined){ -const err122 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -if(data65.optional === undefined){ -const err123 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "optional"},message:"must have required property '"+"optional"+"'"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -if(data65.timeout_millis === undefined){ -const err124 = {instancePath:instancePath+"/definition/hooks/turn_start",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/required",keyword:"required",params:{missingProperty: "timeout_millis"},message:"must have required property '"+"timeout_millis"+"'"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -if(data65.operations !== undefined){ -let data66 = data65.operations; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err125 = {instancePath:instancePath+"/definition/hooks/turn_start/operations",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/type",keyword:"type",params:{type: schema62.properties.definition.properties.hooks.properties.turn_start.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -if(Array.isArray(data66)){ -const len11 = data66.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data66[i11] !== "string"){ -const err126 = {instancePath:instancePath+"/definition/hooks/turn_start/operations/" + i11,schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -} -} -if(data65.optional !== undefined){ -if(typeof data65.optional !== "boolean"){ -const err127 = {instancePath:instancePath+"/definition/hooks/turn_start/optional",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/optional/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data65.timeout_millis !== undefined){ -let data69 = data65.timeout_millis; -if(!((typeof data69 == "number") && (!(data69 % 1) && !isNaN(data69)))){ -const err128 = {instancePath:instancePath+"/definition/hooks/turn_start/timeout_millis",schemaPath:"#/properties/definition/properties/hooks/properties/turn_start/properties/timeout_millis/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -} -} -} -} -} -else { -const err129 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -} -else { -const err130 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -validate61.errors = vErrors; -return errors === 0; -} - -export const DefinitionRegisterResult = validate62; -const schema63 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string"},"created":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/DefinitionRegisterResult","$schema":"http://json-schema.org/draft-07/schema#","title":"DefinitionRegisterResult","required":["id","revision","created"],"additionalProperties":true}; - -function validate62(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/DefinitionRegisterResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.created === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created"},message:"must have required property '"+"created"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.created !== undefined){ -if(typeof data.created !== "boolean"){ -const err5 = {instancePath:instancePath+"/created",schemaPath:"#/properties/created/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate62.errors = vErrors; -return errors === 0; -} - -export const EffortParams = validate63; -const schema64 = {"type":"object","properties":{"effort":{"type":"string"},"persist_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/EffortParams","$schema":"http://json-schema.org/draft-07/schema#","title":"EffortParams","required":["effort","persist_default"],"additionalProperties":true}; - -function validate63(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EffortParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.effort === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.persist_default === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "persist_default"},message:"must have required property '"+"persist_default"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err2 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.persist_default !== undefined){ -if(typeof data.persist_default !== "boolean"){ -const err3 = {instancePath:instancePath+"/persist_default",schemaPath:"#/properties/persist_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate63.errors = vErrors; -return errors === 0; -} - -export const EffortResult = validate64; -const schema65 = {"type":"object","properties":{"effort":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/EffortResult","$schema":"http://json-schema.org/draft-07/schema#","title":"EffortResult","required":["effort"],"additionalProperties":true}; - -function validate64(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EffortResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.effort === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err1 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate64.errors = vErrors; -return errors === 0; -} - -export const Empty = validate65; -const schema66 = {"type":"object","$id":"https://whip.dev/protocol/v6/Empty","$schema":"http://json-schema.org/draft-07/schema#","title":"Empty","additionalProperties":true}; - -function validate65(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Empty" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -} -else { -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -validate65.errors = vErrors; -return errors === 0; -} - -export const EmptyParams = validate66; -const schema67 = {"type":"object","$id":"https://whip.dev/protocol/v6/EmptyParams","$schema":"http://json-schema.org/draft-07/schema#","title":"EmptyParams","additionalProperties":true}; - -function validate66(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EmptyParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -} -else { -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -validate66.errors = vErrors; -return errors === 0; -} - -export const EventNotification = validate67; -const schema68 = {"type":"object","properties":{"event":{"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["root_id","seq","kind"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/EventNotification","$schema":"http://json-schema.org/draft-07/schema#","title":"EventNotification","required":["event"],"additionalProperties":true}; - -function validate67(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/EventNotification" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.event === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "event"},message:"must have required property '"+"event"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.event !== undefined){ -let data0 = data.event; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.root_id === undefined){ -const err1 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.seq === undefined){ -const err2 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.kind === undefined){ -const err3 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.subscription_id !== undefined){ -if(typeof data0.subscription_id !== "string"){ -const err4 = {instancePath:instancePath+"/event/subscription_id",schemaPath:"#/properties/event/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/event/root_id",schemaPath:"#/properties/event/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.seq !== undefined){ -let data3 = data0.seq; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err6 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err7 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/event/seq",schemaPath:"#/properties/event/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err9 = {instancePath:instancePath+"/event/kind",schemaPath:"#/properties/event/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/event",schemaPath:"#/properties/event/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -validate67.errors = vErrors; -return errors === 0; -} - -export const ExecutorBindParams = validate68; -const schema69 = {"type":"object","properties":{"definition":{"type":"string"},"revision":{"type":"string"},"tools":{"type":["null","array"],"items":{"type":"string"}},"hooks":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ExecutorBindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorBindParams","required":["definition","revision","tools"],"additionalProperties":true}; - -function validate68(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorBindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.tools === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err3 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.tools !== undefined){ -let data2 = data.tools; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err5 = {instancePath:instancePath+"/tools",schemaPath:"#/properties/tools/type",keyword:"type",params:{type: schema69.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err6 = {instancePath:instancePath+"/tools/" + i0,schemaPath:"#/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data4 = data.hooks; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err7 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema69.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data4[i1] !== "string"){ -const err8 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate68.errors = vErrors; -return errors === 0; -} - -export const ExecutorBindResult = validate69; -const schema70 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"tools":{"type":["null","array"],"items":{"type":"string"}},"hooks":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ExecutorBindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorBindResult","required":["generation","tools"],"additionalProperties":true}; - -function validate69(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorBindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.tools === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.tools !== undefined){ -let data1 = data.tools; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err5 = {instancePath:instancePath+"/tools",schemaPath:"#/properties/tools/type",keyword:"type",params:{type: schema70.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err6 = {instancePath:instancePath+"/tools/" + i0,schemaPath:"#/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data3 = data.hooks; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err7 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema70.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data3)){ -const len1 = data3.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data3[i1] !== "string"){ -const err8 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate69.errors = vErrors; -return errors === 0; -} - -export const ExecutorPendingParams = validate70; -const schema71 = {"type":"object","properties":{"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ExecutorPendingParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorPendingParams","required":["definition","revision","generation"],"additionalProperties":true}; - -function validate70(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorPendingParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.definition === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.generation === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err3 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.generation !== undefined){ -let data2 = data.generation; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate70.errors = vErrors; -return errors === 0; -} - -export const ExecutorPendingResult = validate71; -const schema72 = {"type":"object","properties":{"invocations":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":true}},"hooks":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"hook":{"type":"string"},"operation":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"request":{"type":"object","properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":true},"resolved":{"type":"object","properties":{"browser_attachments":{"type":["null","array"],"items":{"type":"string"}},"definition":{"type":"string"},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"}},"required":["definition","modules","capabilities","tools","budgets","report"],"additionalProperties":true}},"required":["request","resolved"],"additionalProperties":true},"input":{"type":"string"},"permission_mode":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","hook","permission_mode","deadline_millis"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/ExecutorPendingResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ExecutorPendingResult","required":["invocations"],"additionalProperties":true}; - -function validate71(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ExecutorPendingResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocations === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocations"},message:"must have required property '"+"invocations"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.invocations !== undefined){ -let data0 = data.invocations; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/invocations",schemaPath:"#/properties/invocations/type",keyword:"type",params:{type: schema72.properties.invocations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.invocation_id === undefined){ -const err2 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1.definition === undefined){ -const err3 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.revision === undefined){ -const err4 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.generation === undefined){ -const err5 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.root_id === undefined){ -const err6 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.agent_id === undefined){ -const err7 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.turn_id === undefined){ -const err8 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.tool === undefined){ -const err9 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.input === undefined){ -const err10 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "input"},message:"must have required property '"+"input"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data1.deadline_millis === undefined){ -const err11 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data1.invocation_id !== undefined){ -if(typeof data1.invocation_id !== "string"){ -const err12 = {instancePath:instancePath+"/invocations/" + i0+"/invocation_id",schemaPath:"#/properties/invocations/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.definition !== undefined){ -if(typeof data1.definition !== "string"){ -const err13 = {instancePath:instancePath+"/invocations/" + i0+"/definition",schemaPath:"#/properties/invocations/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.revision !== undefined){ -if(typeof data1.revision !== "string"){ -const err14 = {instancePath:instancePath+"/invocations/" + i0+"/revision",schemaPath:"#/properties/invocations/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.generation !== undefined){ -let data5 = data1.generation; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err15 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err16 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/invocations/" + i0+"/generation",schemaPath:"#/properties/invocations/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err18 = {instancePath:instancePath+"/invocations/" + i0+"/root_id",schemaPath:"#/properties/invocations/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data1.agent_id !== undefined){ -if(typeof data1.agent_id !== "string"){ -const err19 = {instancePath:instancePath+"/invocations/" + i0+"/agent_id",schemaPath:"#/properties/invocations/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.turn_id !== undefined){ -if(typeof data1.turn_id !== "string"){ -const err20 = {instancePath:instancePath+"/invocations/" + i0+"/turn_id",schemaPath:"#/properties/invocations/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data1.tool !== undefined){ -if(typeof data1.tool !== "string"){ -const err21 = {instancePath:instancePath+"/invocations/" + i0+"/tool",schemaPath:"#/properties/invocations/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data1.deadline_millis !== undefined){ -let data10 = data1.deadline_millis; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err22 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err23 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -else { -const err24 = {instancePath:instancePath+"/invocations/" + i0+"/deadline_millis",schemaPath:"#/properties/invocations/items/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath:instancePath+"/invocations/" + i0,schemaPath:"#/properties/invocations/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data.hooks !== undefined){ -let data11 = data.hooks; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err26 = {instancePath:instancePath+"/hooks",schemaPath:"#/properties/hooks/type",keyword:"type",params:{type: schema72.properties.hooks.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data11)){ -const len1 = data11.length; -for(let i1=0; i1<len1; i1++){ -let data12 = data11[i1]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.invocation_id === undefined){ -const err27 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data12.definition === undefined){ -const err28 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data12.revision === undefined){ -const err29 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data12.generation === undefined){ -const err30 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data12.root_id === undefined){ -const err31 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data12.agent_id === undefined){ -const err32 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data12.turn_id === undefined){ -const err33 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data12.hook === undefined){ -const err34 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "hook"},message:"must have required property '"+"hook"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data12.permission_mode === undefined){ -const err35 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "permission_mode"},message:"must have required property '"+"permission_mode"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data12.deadline_millis === undefined){ -const err36 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data12.invocation_id !== undefined){ -if(typeof data12.invocation_id !== "string"){ -const err37 = {instancePath:instancePath+"/hooks/" + i1+"/invocation_id",schemaPath:"#/properties/hooks/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data12.definition !== undefined){ -if(typeof data12.definition !== "string"){ -const err38 = {instancePath:instancePath+"/hooks/" + i1+"/definition",schemaPath:"#/properties/hooks/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data12.revision !== undefined){ -if(typeof data12.revision !== "string"){ -const err39 = {instancePath:instancePath+"/hooks/" + i1+"/revision",schemaPath:"#/properties/hooks/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data12.generation !== undefined){ -let data16 = data12.generation; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err40 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err41 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/hooks/" + i1+"/generation",schemaPath:"#/properties/hooks/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data12.root_id !== undefined){ -if(typeof data12.root_id !== "string"){ -const err43 = {instancePath:instancePath+"/hooks/" + i1+"/root_id",schemaPath:"#/properties/hooks/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data12.agent_id !== undefined){ -if(typeof data12.agent_id !== "string"){ -const err44 = {instancePath:instancePath+"/hooks/" + i1+"/agent_id",schemaPath:"#/properties/hooks/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data12.turn_id !== undefined){ -if(typeof data12.turn_id !== "string"){ -const err45 = {instancePath:instancePath+"/hooks/" + i1+"/turn_id",schemaPath:"#/properties/hooks/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data12.hook !== undefined){ -if(typeof data12.hook !== "string"){ -const err46 = {instancePath:instancePath+"/hooks/" + i1+"/hook",schemaPath:"#/properties/hooks/items/properties/hook/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data12.operation !== undefined){ -if(typeof data12.operation !== "string"){ -const err47 = {instancePath:instancePath+"/hooks/" + i1+"/operation",schemaPath:"#/properties/hooks/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data12.spawn !== undefined){ -let data22 = data12.spawn; -if((data22 !== null) && (!(data22 && typeof data22 == "object" && !Array.isArray(data22)))){ -const err48 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.request === undefined){ -const err49 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/required",keyword:"required",params:{missingProperty: "request"},message:"must have required property '"+"request"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data22.resolved === undefined){ -const err50 = {instancePath:instancePath+"/hooks/" + i1+"/spawn",schemaPath:"#/properties/hooks/items/properties/spawn/required",keyword:"required",params:{missingProperty: "resolved"},message:"must have required property '"+"resolved"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data22.request !== undefined){ -let data23 = data22.request; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt === undefined){ -const err51 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data23.name === undefined){ -const err52 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data23.definition === undefined){ -const err53 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data23.capabilities === undefined){ -const err54 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data23.tools === undefined){ -const err55 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data23.budgets === undefined){ -const err56 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data23.report === undefined){ -const err57 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data23.model === undefined){ -const err58 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data23.provider === undefined){ -const err59 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data23.effort === undefined){ -const err60 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -if(data23.prompt !== undefined){ -if(typeof data23.prompt !== "string"){ -const err61 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/prompt",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data23.name !== undefined){ -if(typeof data23.name !== "string"){ -const err62 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/name",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data23.definition !== undefined){ -if(typeof data23.definition !== "string"){ -const err63 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/definition",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data23.capabilities !== undefined){ -let data27 = data23.capabilities; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err64 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/capabilities",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/capabilities/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err65 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/capabilities/" + i2,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -} -} -if(data23.tools !== undefined){ -let data29 = data23.tools; -if((data29 !== null) && (!(Array.isArray(data29)))){ -const err66 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/tools",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/tools/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(Array.isArray(data29)){ -const len3 = data29.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data29[i3] !== "string"){ -const err67 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/tools/" + i3,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -} -if(data23.budgets !== undefined){ -let data31 = data23.budgets; -if(data31 && typeof data31 == "object" && !Array.isArray(data31)){ -for(const key0 in data31){ -let data32 = data31[key0]; -if(!((typeof data32 == "number") && (!(data32 % 1) && !isNaN(data32)))){ -const err68 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/budgets/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -else { -const err69 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/budgets",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data23.report !== undefined){ -if(typeof data23.report !== "string"){ -const err70 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/report",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data23.model !== undefined){ -if(typeof data23.model !== "string"){ -const err71 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/model",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data23.provider !== undefined){ -if(typeof data23.provider !== "string"){ -const err72 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/provider",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data23.effort !== undefined){ -if(typeof data23.effort !== "string"){ -const err73 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/effort",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data23.browser_attachments !== undefined){ -let data37 = data23.browser_attachments; -if((data37 !== null) && (!(Array.isArray(data37)))){ -const err74 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/browser_attachments",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/browser_attachments/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.request.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -if(Array.isArray(data37)){ -const len4 = data37.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data37[i4] !== "string"){ -const err75 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request/browser_attachments/" + i4,schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -} -} -} -else { -const err76 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/request",schemaPath:"#/properties/hooks/items/properties/spawn/properties/request/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data22.resolved !== undefined){ -let data39 = data22.resolved; -if(data39 && typeof data39 == "object" && !Array.isArray(data39)){ -if(data39.definition === undefined){ -const err77 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data39.modules === undefined){ -const err78 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data39.capabilities === undefined){ -const err79 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data39.tools === undefined){ -const err80 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(data39.budgets === undefined){ -const err81 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data39.report === undefined){ -const err82 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data39.browser_attachments !== undefined){ -let data40 = data39.browser_attachments; -if((data40 !== null) && (!(Array.isArray(data40)))){ -const err83 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/browser_attachments",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/browser_attachments/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(Array.isArray(data40)){ -const len5 = data40.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data40[i5] !== "string"){ -const err84 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/browser_attachments/" + i5,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -} -} -if(data39.definition !== undefined){ -if(typeof data39.definition !== "string"){ -const err85 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/definition",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data39.modules !== undefined){ -let data43 = data39.modules; -if((data43 !== null) && (!(Array.isArray(data43)))){ -const err86 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/modules",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/modules/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(Array.isArray(data43)){ -const len6 = data43.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data43[i6] !== "string"){ -const err87 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/modules/" + i6,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -} -} -if(data39.capabilities !== undefined){ -let data45 = data39.capabilities; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err88 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/capabilities",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/capabilities/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(Array.isArray(data45)){ -const len7 = data45.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data45[i7] !== "string"){ -const err89 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/capabilities/" + i7,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -} -} -if(data39.tools !== undefined){ -let data47 = data39.tools; -if((data47 !== null) && (!(Array.isArray(data47)))){ -const err90 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/tools",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/tools/type",keyword:"type",params:{type: schema72.properties.hooks.items.properties.spawn.properties.resolved.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -if(Array.isArray(data47)){ -const len8 = data47.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data47[i8] !== "string"){ -const err91 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/tools/" + i8,schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -} -} -if(data39.budgets !== undefined){ -let data49 = data39.budgets; -if(data49 && typeof data49 == "object" && !Array.isArray(data49)){ -for(const key1 in data49){ -let data50 = data49[key1]; -if(!((typeof data50 == "number") && (!(data50 % 1) && !isNaN(data50)))){ -const err92 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/budgets/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -else { -const err93 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/budgets",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data39.report !== undefined){ -if(typeof data39.report !== "string"){ -const err94 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved/report",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -} -else { -const err95 = {instancePath:instancePath+"/hooks/" + i1+"/spawn/resolved",schemaPath:"#/properties/hooks/items/properties/spawn/properties/resolved/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -} -} -if(data12.input !== undefined){ -if(typeof data12.input !== "string"){ -const err96 = {instancePath:instancePath+"/hooks/" + i1+"/input",schemaPath:"#/properties/hooks/items/properties/input/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data12.permission_mode !== undefined){ -if(typeof data12.permission_mode !== "string"){ -const err97 = {instancePath:instancePath+"/hooks/" + i1+"/permission_mode",schemaPath:"#/properties/hooks/items/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data12.deadline_millis !== undefined){ -let data54 = data12.deadline_millis; -if(typeof data54 === "string"){ -if(!pattern0.test(data54)){ -const err98 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -if(!(formats0.validate(data54))){ -const err99 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -else { -const err100 = {instancePath:instancePath+"/hooks/" + i1+"/deadline_millis",schemaPath:"#/properties/hooks/items/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -} -else { -const err101 = {instancePath:instancePath+"/hooks/" + i1,schemaPath:"#/properties/hooks/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -} -} -} -} -else { -const err102 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -validate71.errors = vErrors; -return errors === 0; -} - -export const ForkParams = validate72; -const schema73 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"title":{"type":"string"},"cut":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ForkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ForkParams","required":["expected_revision"],"additionalProperties":true}; - -function validate72(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ForkParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.expected_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_revision"},message:"must have required property '"+"expected_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err1 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema73.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err4 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cut !== undefined){ -let data2 = data.cut; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate72.errors = vErrors; -return errors === 0; -} - -export const GatewayStatus = validate73; -const schema74 = {"type":"object","properties":{"state":{"type":"string"},"endpoint":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/GatewayStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"GatewayStatus","required":["state"],"additionalProperties":true}; - -function validate73(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GatewayStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.state === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.state !== undefined){ -if(typeof data.state !== "string"){ -const err1 = {instancePath:instancePath+"/state",schemaPath:"#/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.endpoint !== undefined){ -if(typeof data.endpoint !== "string"){ -const err2 = {instancePath:instancePath+"/endpoint",schemaPath:"#/properties/endpoint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err3 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate73.errors = vErrors; -return errors === 0; -} - -export const GoalContextParams = validate74; -const schema75 = {"type":"object","properties":{"window":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/GoalContextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"GoalContextParams","additionalProperties":true}; - -function validate74(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GoalContextParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.window !== undefined){ -let data0 = data.window; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err0 = {instancePath:instancePath+"/window",schemaPath:"#/properties/window/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate74.errors = vErrors; -return errors === 0; -} - -export const GoalResult = validate75; -const schema76 = {"type":"object","properties":{"goal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/GoalResult","$schema":"http://json-schema.org/draft-07/schema#","title":"GoalResult","required":["goal"],"additionalProperties":true}; - -function validate75(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/GoalResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.goal === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.goal !== undefined){ -if(typeof data.goal !== "string"){ -const err1 = {instancePath:instancePath+"/goal",schemaPath:"#/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate75.errors = vErrors; -return errors === 0; -} - -export const HistoryPageParams = validate76; -const schema77 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"after_seq":{"type":"integer"},"before_seq":{"type":"integer"},"through_seq":{"type":"integer"},"revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"max_bytes":{"type":"integer"},"recent":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HistoryPageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HistoryPageParams","required":["root_id","agent_id","through_seq","limit","max_bytes"],"additionalProperties":true}; - -function validate76(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HistoryPageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.through_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "through_seq"},message:"must have required property '"+"through_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limit === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.max_bytes === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err6 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.after_seq !== undefined){ -let data2 = data.after_seq; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err7 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.before_seq !== undefined){ -let data3 = data.before_seq; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err8 = {instancePath:instancePath+"/before_seq",schemaPath:"#/properties/before_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.through_seq !== undefined){ -let data4 = data.through_seq; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err9 = {instancePath:instancePath+"/through_seq",schemaPath:"#/properties/through_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.revision !== undefined){ -let data5 = data.revision; -if((typeof data5 !== "string") && (data5 !== null)){ -const err10 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: schema77.properties.revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err11 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err12 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -if(data.limit !== undefined){ -let data6 = data.limit; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err13 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data7 = data.max_bytes; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err14 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.recent !== undefined){ -if(typeof data.recent !== "boolean"){ -const err15 = {instancePath:instancePath+"/recent",schemaPath:"#/properties/recent/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -validate76.errors = vErrors; -return errors === 0; -} - -export const HookInvokeParams = validate77; -const schema78 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"hook":{"type":"string"},"operation":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"request":{"type":"object","properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":true},"resolved":{"type":"object","properties":{"browser_attachments":{"type":["null","array"],"items":{"type":"string"}},"definition":{"type":"string"},"modules":{"type":["null","array"],"items":{"type":"string"}},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"}},"required":["definition","modules","capabilities","tools","budgets","report"],"additionalProperties":true}},"required":["request","resolved"],"additionalProperties":true},"input":{"type":"string"},"permission_mode":{"type":"string"},"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/HookInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HookInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","hook","permission_mode","deadline_millis"],"additionalProperties":true}; - -function validate77(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HookInvokeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.definition === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.agent_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.turn_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.hook === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "hook"},message:"must have required property '"+"hook"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.permission_mode === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permission_mode"},message:"must have required property '"+"permission_mode"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err10 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err12 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.generation !== undefined){ -let data3 = data.generation; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err13 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err14 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -else { -const err15 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err16 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err17 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err18 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.hook !== undefined){ -if(typeof data.hook !== "string"){ -const err19 = {instancePath:instancePath+"/hook",schemaPath:"#/properties/hook/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err20 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.spawn !== undefined){ -let data9 = data.spawn; -if((data9 !== null) && (!(data9 && typeof data9 == "object" && !Array.isArray(data9)))){ -const err21 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/type",keyword:"type",params:{type: schema78.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.request === undefined){ -const err22 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "request"},message:"must have required property '"+"request"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data9.resolved === undefined){ -const err23 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "resolved"},message:"must have required property '"+"resolved"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data9.request !== undefined){ -let data10 = data9.request; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.prompt === undefined){ -const err24 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data10.name === undefined){ -const err25 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data10.definition === undefined){ -const err26 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data10.capabilities === undefined){ -const err27 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data10.tools === undefined){ -const err28 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data10.budgets === undefined){ -const err29 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data10.report === undefined){ -const err30 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data10.model === undefined){ -const err31 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data10.provider === undefined){ -const err32 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data10.effort === undefined){ -const err33 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data10.prompt !== undefined){ -if(typeof data10.prompt !== "string"){ -const err34 = {instancePath:instancePath+"/spawn/request/prompt",schemaPath:"#/properties/spawn/properties/request/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data10.name !== undefined){ -if(typeof data10.name !== "string"){ -const err35 = {instancePath:instancePath+"/spawn/request/name",schemaPath:"#/properties/spawn/properties/request/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data10.definition !== undefined){ -if(typeof data10.definition !== "string"){ -const err36 = {instancePath:instancePath+"/spawn/request/definition",schemaPath:"#/properties/spawn/properties/request/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data10.capabilities !== undefined){ -let data14 = data10.capabilities; -if((data14 !== null) && (!(Array.isArray(data14)))){ -const err37 = {instancePath:instancePath+"/spawn/request/capabilities",schemaPath:"#/properties/spawn/properties/request/properties/capabilities/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(Array.isArray(data14)){ -const len0 = data14.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data14[i0] !== "string"){ -const err38 = {instancePath:instancePath+"/spawn/request/capabilities/" + i0,schemaPath:"#/properties/spawn/properties/request/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -} -} -if(data10.tools !== undefined){ -let data16 = data10.tools; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err39 = {instancePath:instancePath+"/spawn/request/tools",schemaPath:"#/properties/spawn/properties/request/properties/tools/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(Array.isArray(data16)){ -const len1 = data16.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data16[i1] !== "string"){ -const err40 = {instancePath:instancePath+"/spawn/request/tools/" + i1,schemaPath:"#/properties/spawn/properties/request/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -} -} -if(data10.budgets !== undefined){ -let data18 = data10.budgets; -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -for(const key0 in data18){ -let data19 = data18[key0]; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err41 = {instancePath:instancePath+"/spawn/request/budgets/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/request/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -else { -const err42 = {instancePath:instancePath+"/spawn/request/budgets",schemaPath:"#/properties/spawn/properties/request/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data10.report !== undefined){ -if(typeof data10.report !== "string"){ -const err43 = {instancePath:instancePath+"/spawn/request/report",schemaPath:"#/properties/spawn/properties/request/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data10.model !== undefined){ -if(typeof data10.model !== "string"){ -const err44 = {instancePath:instancePath+"/spawn/request/model",schemaPath:"#/properties/spawn/properties/request/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data10.provider !== undefined){ -if(typeof data10.provider !== "string"){ -const err45 = {instancePath:instancePath+"/spawn/request/provider",schemaPath:"#/properties/spawn/properties/request/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data10.effort !== undefined){ -if(typeof data10.effort !== "string"){ -const err46 = {instancePath:instancePath+"/spawn/request/effort",schemaPath:"#/properties/spawn/properties/request/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data10.browser_attachments !== undefined){ -let data24 = data10.browser_attachments; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err47 = {instancePath:instancePath+"/spawn/request/browser_attachments",schemaPath:"#/properties/spawn/properties/request/properties/browser_attachments/type",keyword:"type",params:{type: schema78.properties.spawn.properties.request.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(Array.isArray(data24)){ -const len2 = data24.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data24[i2] !== "string"){ -const err48 = {instancePath:instancePath+"/spawn/request/browser_attachments/" + i2,schemaPath:"#/properties/spawn/properties/request/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -} -} -} -else { -const err49 = {instancePath:instancePath+"/spawn/request",schemaPath:"#/properties/spawn/properties/request/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data9.resolved !== undefined){ -let data26 = data9.resolved; -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.definition === undefined){ -const err50 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data26.modules === undefined){ -const err51 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "modules"},message:"must have required property '"+"modules"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data26.capabilities === undefined){ -const err52 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data26.tools === undefined){ -const err53 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data26.budgets === undefined){ -const err54 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data26.report === undefined){ -const err55 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data26.browser_attachments !== undefined){ -let data27 = data26.browser_attachments; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err56 = {instancePath:instancePath+"/spawn/resolved/browser_attachments",schemaPath:"#/properties/spawn/properties/resolved/properties/browser_attachments/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(Array.isArray(data27)){ -const len3 = data27.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data27[i3] !== "string"){ -const err57 = {instancePath:instancePath+"/spawn/resolved/browser_attachments/" + i3,schemaPath:"#/properties/spawn/properties/resolved/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -} -} -if(data26.definition !== undefined){ -if(typeof data26.definition !== "string"){ -const err58 = {instancePath:instancePath+"/spawn/resolved/definition",schemaPath:"#/properties/spawn/properties/resolved/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data26.modules !== undefined){ -let data30 = data26.modules; -if((data30 !== null) && (!(Array.isArray(data30)))){ -const err59 = {instancePath:instancePath+"/spawn/resolved/modules",schemaPath:"#/properties/spawn/properties/resolved/properties/modules/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.modules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(Array.isArray(data30)){ -const len4 = data30.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data30[i4] !== "string"){ -const err60 = {instancePath:instancePath+"/spawn/resolved/modules/" + i4,schemaPath:"#/properties/spawn/properties/resolved/properties/modules/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -} -} -if(data26.capabilities !== undefined){ -let data32 = data26.capabilities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err61 = {instancePath:instancePath+"/spawn/resolved/capabilities",schemaPath:"#/properties/spawn/properties/resolved/properties/capabilities/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(Array.isArray(data32)){ -const len5 = data32.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data32[i5] !== "string"){ -const err62 = {instancePath:instancePath+"/spawn/resolved/capabilities/" + i5,schemaPath:"#/properties/spawn/properties/resolved/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -} -} -if(data26.tools !== undefined){ -let data34 = data26.tools; -if((data34 !== null) && (!(Array.isArray(data34)))){ -const err63 = {instancePath:instancePath+"/spawn/resolved/tools",schemaPath:"#/properties/spawn/properties/resolved/properties/tools/type",keyword:"type",params:{type: schema78.properties.spawn.properties.resolved.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(Array.isArray(data34)){ -const len6 = data34.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data34[i6] !== "string"){ -const err64 = {instancePath:instancePath+"/spawn/resolved/tools/" + i6,schemaPath:"#/properties/spawn/properties/resolved/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data26.budgets !== undefined){ -let data36 = data26.budgets; -if(data36 && typeof data36 == "object" && !Array.isArray(data36)){ -for(const key1 in data36){ -let data37 = data36[key1]; -if(!((typeof data37 == "number") && (!(data37 % 1) && !isNaN(data37)))){ -const err65 = {instancePath:instancePath+"/spawn/resolved/budgets/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/resolved/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -} -else { -const err66 = {instancePath:instancePath+"/spawn/resolved/budgets",schemaPath:"#/properties/spawn/properties/resolved/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data26.report !== undefined){ -if(typeof data26.report !== "string"){ -const err67 = {instancePath:instancePath+"/spawn/resolved/report",schemaPath:"#/properties/spawn/properties/resolved/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -else { -const err68 = {instancePath:instancePath+"/spawn/resolved",schemaPath:"#/properties/spawn/properties/resolved/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -if(data.input !== undefined){ -if(typeof data.input !== "string"){ -const err69 = {instancePath:instancePath+"/input",schemaPath:"#/properties/input/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err70 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data41 = data.deadline_millis; -if(typeof data41 === "string"){ -if(!pattern0.test(data41)){ -const err71 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(!(formats0.validate(data41))){ -const err72 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -else { -const err73 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -} -else { -const err74 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -validate77.errors = vErrors; -return errors === 0; -} - -export const HookResultParams = validate78; -const schema79 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"decision":{"type":"string"},"reason":{"type":"string"},"arguments":true,"spawn":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"name":{"type":"string"},"definition":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}},"tools":{"type":["null","array"],"items":{"type":"string"}},"budgets":{"type":"object","additionalProperties":{"type":"integer"}},"report":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"mcp_tools":true,"browser_attachments":{"type":["null","array"],"items":{"type":"string"}}},"required":["prompt","name","definition","capabilities","tools","budgets","report","model","provider","effort"],"additionalProperties":true},"context":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HookResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HookResultParams","required":["invocation_id","generation"],"additionalProperties":true}; - -function validate78(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HookResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err2 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.decision !== undefined){ -if(typeof data.decision !== "string"){ -const err6 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err7 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.spawn !== undefined){ -let data4 = data.spawn; -if((data4 !== null) && (!(data4 && typeof data4 == "object" && !Array.isArray(data4)))){ -const err8 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/type",keyword:"type",params:{type: schema79.properties.spawn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.prompt === undefined){ -const err9 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.name === undefined){ -const err10 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.definition === undefined){ -const err11 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data4.capabilities === undefined){ -const err12 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data4.tools === undefined){ -const err13 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "tools"},message:"must have required property '"+"tools"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data4.budgets === undefined){ -const err14 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data4.report === undefined){ -const err15 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data4.model === undefined){ -const err16 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data4.provider === undefined){ -const err17 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data4.effort === undefined){ -const err18 = {instancePath:instancePath+"/spawn",schemaPath:"#/properties/spawn/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data4.prompt !== undefined){ -if(typeof data4.prompt !== "string"){ -const err19 = {instancePath:instancePath+"/spawn/prompt",schemaPath:"#/properties/spawn/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err20 = {instancePath:instancePath+"/spawn/name",schemaPath:"#/properties/spawn/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data4.definition !== undefined){ -if(typeof data4.definition !== "string"){ -const err21 = {instancePath:instancePath+"/spawn/definition",schemaPath:"#/properties/spawn/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data4.capabilities !== undefined){ -let data8 = data4.capabilities; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err22 = {instancePath:instancePath+"/spawn/capabilities",schemaPath:"#/properties/spawn/properties/capabilities/type",keyword:"type",params:{type: schema79.properties.spawn.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data8)){ -const len0 = data8.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data8[i0] !== "string"){ -const err23 = {instancePath:instancePath+"/spawn/capabilities/" + i0,schemaPath:"#/properties/spawn/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -} -if(data4.tools !== undefined){ -let data10 = data4.tools; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err24 = {instancePath:instancePath+"/spawn/tools",schemaPath:"#/properties/spawn/properties/tools/type",keyword:"type",params:{type: schema79.properties.spawn.properties.tools.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data10[i1] !== "string"){ -const err25 = {instancePath:instancePath+"/spawn/tools/" + i1,schemaPath:"#/properties/spawn/properties/tools/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data4.budgets !== undefined){ -let data12 = data4.budgets; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -for(const key0 in data12){ -let data13 = data12[key0]; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err26 = {instancePath:instancePath+"/spawn/budgets/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/spawn/properties/budgets/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -else { -const err27 = {instancePath:instancePath+"/spawn/budgets",schemaPath:"#/properties/spawn/properties/budgets/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data4.report !== undefined){ -if(typeof data4.report !== "string"){ -const err28 = {instancePath:instancePath+"/spawn/report",schemaPath:"#/properties/spawn/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data4.model !== undefined){ -if(typeof data4.model !== "string"){ -const err29 = {instancePath:instancePath+"/spawn/model",schemaPath:"#/properties/spawn/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data4.provider !== undefined){ -if(typeof data4.provider !== "string"){ -const err30 = {instancePath:instancePath+"/spawn/provider",schemaPath:"#/properties/spawn/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data4.effort !== undefined){ -if(typeof data4.effort !== "string"){ -const err31 = {instancePath:instancePath+"/spawn/effort",schemaPath:"#/properties/spawn/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data4.browser_attachments !== undefined){ -let data18 = data4.browser_attachments; -if((data18 !== null) && (!(Array.isArray(data18)))){ -const err32 = {instancePath:instancePath+"/spawn/browser_attachments",schemaPath:"#/properties/spawn/properties/browser_attachments/type",keyword:"type",params:{type: schema79.properties.spawn.properties.browser_attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(Array.isArray(data18)){ -const len2 = data18.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data18[i2] !== "string"){ -const err33 = {instancePath:instancePath+"/spawn/browser_attachments/" + i2,schemaPath:"#/properties/spawn/properties/browser_attachments/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -} -} -if(data.context !== undefined){ -if(typeof data.context !== "string"){ -const err34 = {instancePath:instancePath+"/context",schemaPath:"#/properties/context/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err35 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -else { -const err36 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -validate78.errors = vErrors; -return errors === 0; -} - -export const HostAttentionParams = validate79; -const schema80 = {"type":"object","properties":{"after_id":{"type":"string"},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/HostAttentionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostAttentionParams","required":["limit","max_bytes"],"additionalProperties":true}; - -function validate79(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostAttentionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.max_bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.after_id !== undefined){ -if(typeof data.after_id !== "string"){ -const err2 = {instancePath:instancePath+"/after_id",schemaPath:"#/properties/after_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.limit !== undefined){ -let data1 = data.limit; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err3 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data2 = data.max_bytes; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err4 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate79.errors = vErrors; -return errors === 0; -} - -export const HostAttentionResult = validate80; -const schema81 = {"type":"object","properties":{"items":{"type":["null","array"],"items":{"type":"object","properties":{"root_id":{"type":"string"},"title":{"type":"string"},"active_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_permissions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":true},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":true}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":true}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":true}}},"additionalProperties":true}},"truncated":{"type":"boolean"}},"required":["root_id","title","active_agents","pending_permissions","questions","truncated"],"additionalProperties":true}},"next_after_id":{"type":"string"},"has_more":{"type":"boolean"},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostAttentionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostAttentionResult","required":["items","has_more","truncated"],"additionalProperties":true}; - -function validate80(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostAttentionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.has_more === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.truncated === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.items !== undefined){ -let data0 = data.items; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema81.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err4 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.title === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.active_agents === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "active_agents"},message:"must have required property '"+"active_agents"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.pending_permissions === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_permissions"},message:"must have required property '"+"pending_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.questions === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "questions"},message:"must have required property '"+"questions"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.truncated === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err10 = {instancePath:instancePath+"/items/" + i0+"/root_id",schemaPath:"#/properties/items/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.title !== undefined){ -if(typeof data1.title !== "string"){ -const err11 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.active_agents !== undefined){ -let data4 = data1.active_agents; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err12 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err13 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -else { -const err14 = {instancePath:instancePath+"/items/" + i0+"/active_agents",schemaPath:"#/properties/items/items/properties/active_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.pending_permissions !== undefined){ -let data5 = data1.pending_permissions; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err15 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err16 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data1.questions !== undefined){ -let data6 = data1.questions; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/questions",schemaPath:"#/properties/items/items/properties/questions/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(Array.isArray(data6)){ -const len1 = data6.length; -for(let i1=0; i1<len1; i1++){ -let data7 = data6[i1]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.turn_id !== undefined){ -if(typeof data7.turn_id !== "string"){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/turn_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/root_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/agent_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.sender_agent_id !== undefined){ -if(typeof data7.sender_agent_id !== "string"){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/sender_agent_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.inbox_seq !== undefined){ -let data12 = data7.inbox_seq; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_seq",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.inbox_kind !== undefined){ -if(typeof data7.inbox_kind !== "string"){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/inbox_kind",schemaPath:"#/properties/items/items/properties/questions/items/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data7.delivery !== undefined){ -if(typeof data7.delivery !== "string"){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/delivery",schemaPath:"#/properties/items/items/properties/questions/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data7.message_id !== undefined){ -if(typeof data7.message_id !== "string"){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/message_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data7.phase !== undefined){ -if(typeof data7.phase !== "string"){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/phase",schemaPath:"#/properties/items/items/properties/questions/items/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data7.status !== undefined){ -if(typeof data7.status !== "string"){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/status",schemaPath:"#/properties/items/items/properties/questions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data7.terminal_cause !== undefined){ -if(typeof data7.terminal_cause !== "string"){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/terminal_cause",schemaPath:"#/properties/items/items/properties/questions/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data7.command_client_id !== undefined){ -if(typeof data7.command_client_id !== "string"){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command_client_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data7.command_id !== undefined){ -if(typeof data7.command_id !== "string"){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data7.operation_id !== undefined){ -if(typeof data7.operation_id !== "string"){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/operation_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data7.trace_id !== undefined){ -if(typeof data7.trace_id !== "string"){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/trace_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data7.schedule_id !== undefined){ -let data23 = data7.schedule_id; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/schedule_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data7.slot !== undefined){ -if(typeof data7.slot !== "string"){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/slot",schemaPath:"#/properties/items/items/properties/questions/items/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data7.error !== undefined){ -if(typeof data7.error !== "string"){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/error",schemaPath:"#/properties/items/items/properties/questions/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data7.model_call !== undefined){ -let data26 = data7.model_call; -if((data26 !== null) && (!(data26 && typeof data26 == "object" && !Array.isArray(data26)))){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.id === undefined){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data26.logical_id === undefined){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data26.number === undefined){ -const err42 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data26.purpose === undefined){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data26.usage_source === undefined){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data26.cost_source === undefined){ -const err45 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data26.tokens === undefined){ -const err46 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data26.cost_micros === undefined){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data26.elapsed_millis === undefined){ -const err48 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data26.exhausted === undefined){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data26.id !== undefined){ -if(typeof data26.id !== "string"){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/id",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data26.logical_id !== undefined){ -if(typeof data26.logical_id !== "string"){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/logical_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data26.number !== undefined){ -let data29 = data26.number; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/number",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data26.purpose !== undefined){ -if(typeof data26.purpose !== "string"){ -const err53 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/purpose",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data26.usage_source !== undefined){ -if(typeof data26.usage_source !== "string"){ -const err54 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/usage_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data26.cost_source !== undefined){ -if(typeof data26.cost_source !== "string"){ -const err55 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data26.tokens !== undefined){ -let data33 = data26.tokens; -if(typeof data33 === "string"){ -if(!pattern0.test(data33)){ -const err56 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(!(formats0.validate(data33))){ -const err57 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -else { -const err58 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/tokens",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data26.cost_micros !== undefined){ -let data34 = data26.cost_micros; -if(typeof data34 === "string"){ -if(!pattern0.test(data34)){ -const err59 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(!(formats0.validate(data34))){ -const err60 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -else { -const err61 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/cost_micros",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data26.elapsed_millis !== undefined){ -let data35 = data26.elapsed_millis; -if(typeof data35 === "string"){ -if(!pattern0.test(data35)){ -const err62 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(!(formats0.validate(data35))){ -const err63 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -else { -const err64 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/elapsed_millis",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data26.exhausted !== undefined){ -if(typeof data26.exhausted !== "boolean"){ -const err65 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/model_call/exhausted",schemaPath:"#/properties/items/items/properties/questions/items/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -} -} -if(data7.acknowledged_inbox !== undefined){ -let data37 = data7.acknowledged_inbox; -if(Array.isArray(data37)){ -const len2 = data37.length; -for(let i2=0; i2<len2; i2++){ -let data38 = data37[i2]; -if(typeof data38 === "string"){ -if(!pattern0.test(data38)){ -const err66 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(!(formats0.validate(data38))){ -const err67 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -else { -const err68 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox/" + i2,schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -else { -const err69 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/acknowledged_inbox",schemaPath:"#/properties/items/items/properties/questions/items/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data7.subscription_id !== undefined){ -if(typeof data7.subscription_id !== "string"){ -const err70 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/subscription_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data7.key !== undefined){ -if(typeof data7.key !== "string"){ -const err71 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/key",schemaPath:"#/properties/items/items/properties/questions/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data7.version !== undefined){ -let data41 = data7.version; -if(typeof data41 === "string"){ -if(!pattern0.test(data41)){ -const err72 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(!(formats0.validate(data41))){ -const err73 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -else { -const err74 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/version",schemaPath:"#/properties/items/items/properties/questions/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data7.expected_version !== undefined){ -let data42 = data7.expected_version; -if(typeof data42 === "string"){ -if(!pattern0.test(data42)){ -const err75 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(!(formats0.validate(data42))){ -const err76 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -else { -const err77 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/expected_version",schemaPath:"#/properties/items/items/properties/questions/items/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data7.restored !== undefined){ -let data43 = data7.restored; -if((data43 !== null) && (!(Array.isArray(data43)))){ -const err78 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/restored",schemaPath:"#/properties/items/items/properties/questions/items/properties/restored/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(Array.isArray(data43)){ -const len3 = data43.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data43[i3] !== "string"){ -const err79 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/restored/" + i3,schemaPath:"#/properties/items/items/properties/questions/items/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -} -} -if(data7.not_restored !== undefined){ -let data45 = data7.not_restored; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err80 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(Array.isArray(data45)){ -const len4 = data45.length; -for(let i4=0; i4<len4; i4++){ -let data46 = data45[i4]; -if(data46 && typeof data46 == "object" && !Array.isArray(data46)){ -if(data46.name === undefined){ -const err81 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data46.reason === undefined){ -const err82 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data46.name !== undefined){ -if(typeof data46.name !== "string"){ -const err83 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4+"/name",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -if(data46.reason !== undefined){ -if(typeof data46.reason !== "string"){ -const err84 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4+"/reason",schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -} -else { -const err85 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/not_restored/" + i4,schemaPath:"#/properties/items/items/properties/questions/items/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -} -} -if(data7.attempt !== undefined){ -if(typeof data7.attempt !== "string"){ -const err86 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/attempt",schemaPath:"#/properties/items/items/properties/questions/items/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data7.budget_kind !== undefined){ -if(typeof data7.budget_kind !== "string"){ -const err87 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/budget_kind",schemaPath:"#/properties/items/items/properties/questions/items/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data7.amount !== undefined){ -let data51 = data7.amount; -if(typeof data51 === "string"){ -if(!pattern0.test(data51)){ -const err88 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(!(formats0.validate(data51))){ -const err89 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -else { -const err90 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/amount",schemaPath:"#/properties/items/items/properties/questions/items/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data7.limit !== undefined){ -let data52 = data7.limit; -if(typeof data52 === "string"){ -if(!pattern0.test(data52)){ -const err91 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -if(!(formats0.validate(data52))){ -const err92 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -else { -const err93 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/limit",schemaPath:"#/properties/items/items/properties/questions/items/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data7.used !== undefined){ -let data53 = data7.used; -if(typeof data53 === "string"){ -if(!pattern0.test(data53)){ -const err94 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(!(formats0.validate(data53))){ -const err95 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -else { -const err96 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/used",schemaPath:"#/properties/items/items/properties/questions/items/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data7.reserved !== undefined){ -let data54 = data7.reserved; -if(typeof data54 === "string"){ -if(!pattern0.test(data54)){ -const err97 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -if(!(formats0.validate(data54))){ -const err98 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -else { -const err99 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/reserved",schemaPath:"#/properties/items/items/properties/questions/items/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data7.capability_id !== undefined){ -if(typeof data7.capability_id !== "string"){ -const err100 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/capability_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data7.generation !== undefined){ -let data56 = data7.generation; -if(typeof data56 === "string"){ -if(!pattern0.test(data56)){ -const err101 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(!(formats0.validate(data56))){ -const err102 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -} -else { -const err103 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/generation",schemaPath:"#/properties/items/items/properties/questions/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data7.permission_id !== undefined){ -if(typeof data7.permission_id !== "string"){ -const err104 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/permission_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data7.operation !== undefined){ -if(typeof data7.operation !== "string"){ -const err105 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/operation",schemaPath:"#/properties/items/items/properties/questions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data7.canonical_path !== undefined){ -if(typeof data7.canonical_path !== "string"){ -const err106 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/canonical_path",schemaPath:"#/properties/items/items/properties/questions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data7.request_digest !== undefined){ -if(typeof data7.request_digest !== "string"){ -const err107 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/request_digest",schemaPath:"#/properties/items/items/properties/questions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data7.command !== undefined){ -if(typeof data7.command !== "string"){ -const err108 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/command",schemaPath:"#/properties/items/items/properties/questions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data7.rule !== undefined){ -if(typeof data7.rule !== "string"){ -const err109 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/rule",schemaPath:"#/properties/items/items/properties/questions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data7.rule_source !== undefined){ -if(typeof data7.rule_source !== "string"){ -const err110 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/rule_source",schemaPath:"#/properties/items/items/properties/questions/items/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data7.question_id !== undefined){ -if(typeof data7.question_id !== "string"){ -const err111 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/question_id",schemaPath:"#/properties/items/items/properties/questions/items/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -if(data7.question !== undefined){ -if(typeof data7.question !== "string"){ -const err112 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/question",schemaPath:"#/properties/items/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -} -if(data7.options !== undefined){ -let data66 = data7.options; -if((data66 !== null) && (!(Array.isArray(data66)))){ -const err113 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(Array.isArray(data66)){ -const len5 = data66.length; -for(let i5=0; i5<len5; i5++){ -let data67 = data66[i5]; -if(data67 && typeof data67 == "object" && !Array.isArray(data67)){ -if(data67.label === undefined){ -const err114 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5,schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data67.label !== undefined){ -if(typeof data67.label !== "string"){ -const err115 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/label",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data67.description !== undefined){ -if(typeof data67.description !== "string"){ -const err116 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/description",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data67.recommended !== undefined){ -if(typeof data67.recommended !== "boolean"){ -const err117 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5+"/recommended",schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -} -else { -const err118 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/options/" + i5,schemaPath:"#/properties/items/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -} -} -if(data7.multiple !== undefined){ -if(typeof data7.multiple !== "boolean"){ -const err119 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/multiple",schemaPath:"#/properties/items/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -if(data7.questions !== undefined){ -let data72 = data7.questions; -if((data72 !== null) && (!(Array.isArray(data72)))){ -const err120 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(Array.isArray(data72)){ -const len6 = data72.length; -for(let i6=0; i6<len6; i6++){ -let data73 = data72[i6]; -if(data73 && typeof data73 == "object" && !Array.isArray(data73)){ -if(data73.question === undefined){ -const err121 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data73.question !== undefined){ -if(typeof data73.question !== "string"){ -const err122 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/question",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data73.options !== undefined){ -let data75 = data73.options; -if((data75 !== null) && (!(Array.isArray(data75)))){ -const err123 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -if(Array.isArray(data75)){ -const len7 = data75.length; -for(let i7=0; i7<len7; i7++){ -let data76 = data75[i7]; -if(data76 && typeof data76 == "object" && !Array.isArray(data76)){ -if(data76.label === undefined){ -const err124 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -if(data76.label !== undefined){ -if(typeof data76.label !== "string"){ -const err125 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/label",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data76.description !== undefined){ -if(typeof data76.description !== "string"){ -const err126 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/description",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -if(data76.recommended !== undefined){ -if(typeof data76.recommended !== "boolean"){ -const err127 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7+"/recommended",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -} -else { -const err128 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/options/" + i7,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -} -} -if(data73.multiple !== undefined){ -if(typeof data73.multiple !== "boolean"){ -const err129 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6+"/multiple",schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -} -else { -const err130 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/questions/" + i6,schemaPath:"#/properties/items/items/properties/questions/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -} -} -if(data7.answer !== undefined){ -let data81 = data7.answer; -if((data81 !== null) && (!(Array.isArray(data81)))){ -const err131 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answer",schemaPath:"#/properties/items/items/properties/questions/items/properties/answer/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -if(Array.isArray(data81)){ -const len8 = data81.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data81[i8] !== "string"){ -const err132 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answer/" + i8,schemaPath:"#/properties/items/items/properties/questions/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -} -} -if(data7.dismissed !== undefined){ -if(typeof data7.dismissed !== "boolean"){ -const err133 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/dismissed",schemaPath:"#/properties/items/items/properties/questions/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data7.answers !== undefined){ -let data84 = data7.answers; -if((data84 !== null) && (!(Array.isArray(data84)))){ -const err134 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -if(Array.isArray(data84)){ -const len9 = data84.length; -for(let i9=0; i9<len9; i9++){ -let data85 = data84[i9]; -if(data85 && typeof data85 == "object" && !Array.isArray(data85)){ -if(data85.answer !== undefined){ -let data86 = data85.answer; -if((data86 !== null) && (!(Array.isArray(data86)))){ -const err135 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/answer",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema81.properties.items.items.properties.questions.items.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -if(Array.isArray(data86)){ -const len10 = data86.length; -for(let i10=0; i10<len10; i10++){ -if(typeof data86[i10] !== "string"){ -const err136 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/answer/" + i10,schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -} -} -if(data85.dismissed !== undefined){ -if(typeof data85.dismissed !== "boolean"){ -const err137 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9+"/dismissed",schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -} -else { -const err138 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1+"/answers/" + i9,schemaPath:"#/properties/items/items/properties/questions/items/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -} -else { -const err139 = {instancePath:instancePath+"/items/" + i0+"/questions/" + i1,schemaPath:"#/properties/items/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -} -} -if(data1.truncated !== undefined){ -if(typeof data1.truncated !== "boolean"){ -const err140 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -} -else { -const err141 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -} -} -if(data.next_after_id !== undefined){ -if(typeof data.next_after_id !== "string"){ -const err142 = {instancePath:instancePath+"/next_after_id",schemaPath:"#/properties/next_after_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err143 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err144 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -} -} -else { -const err145 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -validate80.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryParams = validate81; -const schema82 = {"type":"object","properties":{"path":{"type":"string"},"after":{"type":"string"},"prefix":{"type":"string"},"show_hidden":{"type":"boolean"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryParams","required":["limit"],"additionalProperties":true}; - -function validate81(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err1 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.after !== undefined){ -if(typeof data.after !== "string"){ -const err2 = {instancePath:instancePath+"/after",schemaPath:"#/properties/after/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err3 = {instancePath:instancePath+"/prefix",schemaPath:"#/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.show_hidden !== undefined){ -if(typeof data.show_hidden !== "boolean"){ -const err4 = {instancePath:instancePath+"/show_hidden",schemaPath:"#/properties/show_hidden/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.limit !== undefined){ -let data4 = data.limit; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err5 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate81.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryPickParams = validate82; -const schema83 = {"type":"object","properties":{"start":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryPickParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryPickParams","additionalProperties":true}; - -function validate82(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryPickParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.start !== undefined){ -if(typeof data.start !== "string"){ -const err0 = {instancePath:instancePath+"/start",schemaPath:"#/properties/start/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate82.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryPickResult = validate83; -const schema84 = {"type":"object","properties":{"path":{"type":"string"},"cancelled":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryPickResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryPickResult","required":["cancelled"],"additionalProperties":true}; - -function validate83(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryPickResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cancelled === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cancelled"},message:"must have required property '"+"cancelled"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err1 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.cancelled !== undefined){ -if(typeof data.cancelled !== "boolean"){ -const err2 = {instancePath:instancePath+"/cancelled",schemaPath:"#/properties/cancelled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate83.errors = vErrors; -return errors === 0; -} - -export const HostDirectoryResult = validate84; -const schema85 = {"type":"object","properties":{"path":{"type":"string"},"parent":{"type":"string"},"entries":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"path":{"type":"string"}},"required":["name","path"],"additionalProperties":true}},"next_after":{"type":"string"},"has_more":{"type":"boolean"},"truncated":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/HostDirectoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"HostDirectoryResult","required":["path","parent","entries","has_more","truncated"],"additionalProperties":true}; - -function validate84(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostDirectoryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.parent === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "parent"},message:"must have required property '"+"parent"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.entries === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "entries"},message:"must have required property '"+"entries"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.truncated === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err5 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.parent !== undefined){ -if(typeof data.parent !== "string"){ -const err6 = {instancePath:instancePath+"/parent",schemaPath:"#/properties/parent/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.entries !== undefined){ -let data2 = data.entries; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err7 = {instancePath:instancePath+"/entries",schemaPath:"#/properties/entries/type",keyword:"type",params:{type: schema85.properties.entries.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -let data3 = data2[i0]; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.name === undefined){ -const err8 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data3.path === undefined){ -const err9 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data3.name !== undefined){ -if(typeof data3.name !== "string"){ -const err10 = {instancePath:instancePath+"/entries/" + i0+"/name",schemaPath:"#/properties/entries/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data3.path !== undefined){ -if(typeof data3.path !== "string"){ -const err11 = {instancePath:instancePath+"/entries/" + i0+"/path",schemaPath:"#/properties/entries/items/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/entries/" + i0,schemaPath:"#/properties/entries/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.next_after !== undefined){ -if(typeof data.next_after !== "string"){ -const err13 = {instancePath:instancePath+"/next_after",schemaPath:"#/properties/next_after/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err14 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.truncated !== undefined){ -if(typeof data.truncated !== "boolean"){ -const err15 = {instancePath:instancePath+"/truncated",schemaPath:"#/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -validate84.errors = vErrors; -return errors === 0; -} - -export const HostSkillCompletionParams = validate85; -const schema86 = {"$id":"https://whip.dev/protocol/v6/HostSkillCompletionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostSkillCompletionParams","allOf":[{"type":"object","properties":{"scope":{"type":"string"},"cwd":{"type":"string"},"definition":{"type":"string"},"permission_mode":{"type":"string"},"prefix":{"type":"string"},"limit":{"type":"integer"}},"required":["prefix","limit"],"additionalProperties":true},{"oneOf":[{"type":"object","properties":{"cwd":{"type":"string","pattern":"^[\\s\\S]+$"},"scope":{"type":"string","enum":[""]}},"required":["cwd"]},{"type":"object","properties":{"cwd":{"type":"string","enum":[""]},"scope":{"type":"string","enum":["global"]}},"required":["scope"]}]}]}; -const pattern80 = new RegExp("^[\\s\\S]+$", "u"); - -function validate85(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostSkillCompletionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.prefix === undefined){ -const err0 = {instancePath,schemaPath:"#/allOf/0/required",keyword:"required",params:{missingProperty: "prefix"},message:"must have required property '"+"prefix"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.limit === undefined){ -const err1 = {instancePath,schemaPath:"#/allOf/0/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.scope !== undefined){ -if(typeof data.scope !== "string"){ -const err2 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/0/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err3 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/0/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err4 = {instancePath:instancePath+"/definition",schemaPath:"#/allOf/0/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err5 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/allOf/0/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.prefix !== undefined){ -if(typeof data.prefix !== "string"){ -const err6 = {instancePath:instancePath+"/prefix",schemaPath:"#/allOf/0/properties/prefix/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.limit !== undefined){ -let data5 = data.limit; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err7 = {instancePath:instancePath+"/limit",schemaPath:"#/allOf/0/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/allOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -const _errs16 = errors; -let valid2 = false; -let passing0 = null; -const _errs17 = errors; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cwd === undefined){ -const err9 = {instancePath,schemaPath:"#/allOf/1/oneOf/0/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.cwd !== undefined){ -let data6 = data.cwd; -if(typeof data6 === "string"){ -if(!pattern80.test(data6)){ -const err10 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/0/properties/cwd/pattern",keyword:"pattern",params:{pattern: "^[\\s\\S]+$"},message:"must match pattern \""+"^[\\s\\S]+$"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/0/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.scope !== undefined){ -let data7 = data.scope; -if(typeof data7 !== "string"){ -const err12 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/0/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(data7 === "")){ -const err13 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/0/properties/scope/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[0].properties.scope.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/allOf/1/oneOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -var _valid0 = _errs17 === errors; -if(_valid0){ -valid2 = true; -passing0 = 0; -} -const _errs23 = errors; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.scope === undefined){ -const err15 = {instancePath,schemaPath:"#/allOf/1/oneOf/1/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data.cwd !== undefined){ -let data8 = data.cwd; -if(typeof data8 !== "string"){ -const err16 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/1/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(data8 === "")){ -const err17 = {instancePath:instancePath+"/cwd",schemaPath:"#/allOf/1/oneOf/1/properties/cwd/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[1].properties.cwd.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.scope !== undefined){ -let data9 = data.scope; -if(typeof data9 !== "string"){ -const err18 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/1/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(data9 === "global")){ -const err19 = {instancePath:instancePath+"/scope",schemaPath:"#/allOf/1/oneOf/1/properties/scope/enum",keyword:"enum",params:{allowedValues: schema86.allOf[1].oneOf[1].properties.scope.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath,schemaPath:"#/allOf/1/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -var _valid0 = _errs23 === errors; -if(_valid0 && valid2){ -valid2 = false; -passing0 = [passing0, 1]; -} -else { -if(_valid0){ -valid2 = true; -passing0 = 1; -} -} -if(!valid2){ -const err21 = {instancePath,schemaPath:"#/allOf/1/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -else { -errors = _errs16; -if(vErrors !== null){ -if(_errs16){ -vErrors.length = _errs16; -} -else { -vErrors = null; -} -} -} -validate85.errors = vErrors; -return errors === 0; -} - -export const HostThemeResolveParams = validate86; -const schema87 = {"type":"object","properties":{"name":{"type":"string"},"json":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/HostThemeResolveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"HostThemeResolveParams","additionalProperties":true}; - -function validate86(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/HostThemeResolveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err0 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.json !== undefined){ -if(typeof data.json !== "string"){ -const err1 = {instancePath:instancePath+"/json",schemaPath:"#/properties/json/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate86.errors = vErrors; -return errors === 0; -} - -export const IDParams = validate87; -const schema88 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/IDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"IDParams","required":["id"],"additionalProperties":true}; - -function validate87(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/IDParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err1 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate87.errors = vErrors; -return errors === 0; -} - -export const InboxControlResult = validate88; -const schema89 = {"type":"object","properties":{"agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/InboxControlResult","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxControlResult","required":["agent_id","inbox_seq","status"],"additionalProperties":true}; - -function validate88(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxControlResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.agent_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.status === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err3 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err7 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate88.errors = vErrors; -return errors === 0; -} - -export const InboxRemoveParams = validate89; -const schema90 = {"type":"object","properties":{"id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/InboxRemoveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxRemoveParams","required":["id","inbox_seq"],"additionalProperties":true}; - -function validate89(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxRemoveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate89.errors = vErrors; -return errors === 0; -} - -export const InboxSteerParams = validate90; -const schema91 = {"type":"object","properties":{"id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"turn_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/InboxSteerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InboxSteerParams","required":["id","inbox_seq","turn_id"],"additionalProperties":true}; - -function validate90(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InboxSteerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.inbox_seq === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox_seq"},message:"must have required property '"+"inbox_seq"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.turn_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data1 = data.inbox_seq; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err7 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate90.errors = vErrors; -return errors === 0; -} - -export const InitializeParams = validate91; -const schema92 = {"type":"object","properties":{"protocol_major":{"type":"integer"},"build_id":{"type":"string"},"client_kind":{"type":"string"},"client_id":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/InitializeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"InitializeParams","required":["protocol_major","build_id","client_kind","client_id"],"additionalProperties":true}; - -function validate91(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InitializeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.protocol_major === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_major"},message:"must have required property '"+"protocol_major"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.build_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.client_kind === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "client_kind"},message:"must have required property '"+"client_kind"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.client_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "client_id"},message:"must have required property '"+"client_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.protocol_major !== undefined){ -let data0 = data.protocol_major; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err4 = {instancePath:instancePath+"/protocol_major",schemaPath:"#/properties/protocol_major/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err5 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.client_kind !== undefined){ -if(typeof data.client_kind !== "string"){ -const err6 = {instancePath:instancePath+"/client_kind",schemaPath:"#/properties/client_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.client_id !== undefined){ -if(typeof data.client_id !== "string"){ -const err7 = {instancePath:instancePath+"/client_id",schemaPath:"#/properties/client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data4 = data.capabilities; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err8 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema92.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err9 = {instancePath:instancePath+"/capabilities/" + i0,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate91.errors = vErrors; -return errors === 0; -} - -export const InitializeResult = validate92; -const schema93 = {"type":"object","properties":{"execution_engines":{"type":["null","array"],"items":{"type":"object","properties":{"bridge_sha256":{"type":"string"},"build":{"type":"string"},"abi":{"type":"string"},"profile":{"type":"string"},"fidelity":{"type":"string"},"guide_sha256":{"type":"string"},"features":{"type":["null","array"],"items":{"type":"string"}},"default_limits":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"id":{"type":"string"},"language":{"type":"string"},"label":{"type":"string"}},"required":["id","language","label"],"additionalProperties":true}},"default_execution_engine":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"surface":{"type":"string"},"execution":{"type":"string"},"permission":{"type":"string"},"sensitive":{"type":"boolean"}},"required":["name","surface","execution","permission"],"additionalProperties":true}},"limits":{"type":"object","properties":{"frame_bytes":{"type":"integer"},"connections":{"type":"integer"},"in_flight_requests":{"type":"integer"},"outbound_messages":{"type":"integer"},"outbound_bytes":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_subscriptions":{"type":"integer"},"content_chunk_bytes":{"type":"integer"},"upload_bytes":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["frame_bytes","connections","in_flight_requests","outbound_messages","outbound_bytes","root_subscriptions","content_chunk_bytes","upload_bytes"],"additionalProperties":true},"negotiated_capabilities":{"type":["null","array"],"items":{"type":"string"}},"protocol_minor":{"type":"integer"},"runtime_id":{"type":"string"},"connection_id":{"type":"string"},"host_platform":{"type":"string"},"host_architecture":{"type":"string"},"network_endpoint":{"type":"string"},"protocol_major":{"type":"integer"},"build_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pid":{"type":"integer"},"started_at":{"type":"string"},"capabilities":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/InitializeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"InitializeResult","required":["execution_engines","default_execution_engine","operations","limits","negotiated_capabilities","protocol_minor","runtime_id","connection_id","host_platform","host_architecture","protocol_major","build_id","generation","capabilities"],"additionalProperties":true}; - -function validate92(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/InitializeResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.execution_engines === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "execution_engines"},message:"must have required property '"+"execution_engines"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.default_execution_engine === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_execution_engine"},message:"must have required property '"+"default_execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.operations === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.limits === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limits"},message:"must have required property '"+"limits"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.negotiated_capabilities === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "negotiated_capabilities"},message:"must have required property '"+"negotiated_capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.protocol_minor === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_minor"},message:"must have required property '"+"protocol_minor"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.runtime_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.connection_id === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "connection_id"},message:"must have required property '"+"connection_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.host_platform === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "host_platform"},message:"must have required property '"+"host_platform"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.host_architecture === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "host_architecture"},message:"must have required property '"+"host_architecture"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.protocol_major === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "protocol_major"},message:"must have required property '"+"protocol_major"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.build_id === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.generation === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.capabilities === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data.execution_engines !== undefined){ -let data0 = data.execution_engines; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err14 = {instancePath:instancePath+"/execution_engines",schemaPath:"#/properties/execution_engines/type",keyword:"type",params:{type: schema93.properties.execution_engines.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err15 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data1.language === undefined){ -const err16 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "language"},message:"must have required property '"+"language"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data1.label === undefined){ -const err17 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data1.bridge_sha256 !== undefined){ -if(typeof data1.bridge_sha256 !== "string"){ -const err18 = {instancePath:instancePath+"/execution_engines/" + i0+"/bridge_sha256",schemaPath:"#/properties/execution_engines/items/properties/bridge_sha256/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data1.build !== undefined){ -if(typeof data1.build !== "string"){ -const err19 = {instancePath:instancePath+"/execution_engines/" + i0+"/build",schemaPath:"#/properties/execution_engines/items/properties/build/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data1.abi !== undefined){ -if(typeof data1.abi !== "string"){ -const err20 = {instancePath:instancePath+"/execution_engines/" + i0+"/abi",schemaPath:"#/properties/execution_engines/items/properties/abi/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data1.profile !== undefined){ -if(typeof data1.profile !== "string"){ -const err21 = {instancePath:instancePath+"/execution_engines/" + i0+"/profile",schemaPath:"#/properties/execution_engines/items/properties/profile/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data1.fidelity !== undefined){ -if(typeof data1.fidelity !== "string"){ -const err22 = {instancePath:instancePath+"/execution_engines/" + i0+"/fidelity",schemaPath:"#/properties/execution_engines/items/properties/fidelity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data1.guide_sha256 !== undefined){ -if(typeof data1.guide_sha256 !== "string"){ -const err23 = {instancePath:instancePath+"/execution_engines/" + i0+"/guide_sha256",schemaPath:"#/properties/execution_engines/items/properties/guide_sha256/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data1.features !== undefined){ -let data8 = data1.features; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err24 = {instancePath:instancePath+"/execution_engines/" + i0+"/features",schemaPath:"#/properties/execution_engines/items/properties/features/type",keyword:"type",params:{type: schema93.properties.execution_engines.items.properties.features.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err25 = {instancePath:instancePath+"/execution_engines/" + i0+"/features/" + i1,schemaPath:"#/properties/execution_engines/items/properties/features/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data1.default_limits !== undefined){ -let data10 = data1.default_limits; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -for(const key0 in data10){ -let data11 = data10[key0]; -if(!((typeof data11 == "number") && (!(data11 % 1) && !isNaN(data11)))){ -const err26 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/execution_engines/items/properties/default_limits/additionalProperties/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(typeof data11 == "number"){ -if(data11 < 0 || isNaN(data11)){ -const err27 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/execution_engines/items/properties/default_limits/additionalProperties/minimum",keyword:"minimum",params:{comparison: ">=", limit: 0},message:"must be >= 0"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -} -else { -const err28 = {instancePath:instancePath+"/execution_engines/" + i0+"/default_limits",schemaPath:"#/properties/execution_engines/items/properties/default_limits/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err29 = {instancePath:instancePath+"/execution_engines/" + i0+"/id",schemaPath:"#/properties/execution_engines/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data1.language !== undefined){ -if(typeof data1.language !== "string"){ -const err30 = {instancePath:instancePath+"/execution_engines/" + i0+"/language",schemaPath:"#/properties/execution_engines/items/properties/language/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err31 = {instancePath:instancePath+"/execution_engines/" + i0+"/label",schemaPath:"#/properties/execution_engines/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -else { -const err32 = {instancePath:instancePath+"/execution_engines/" + i0,schemaPath:"#/properties/execution_engines/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -} -if(data.default_execution_engine !== undefined){ -if(typeof data.default_execution_engine !== "string"){ -const err33 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data.operations !== undefined){ -let data16 = data.operations; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err34 = {instancePath:instancePath+"/operations",schemaPath:"#/properties/operations/type",keyword:"type",params:{type: schema93.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(Array.isArray(data16)){ -const len2 = data16.length; -for(let i2=0; i2<len2; i2++){ -let data17 = data16[i2]; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.name === undefined){ -const err35 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data17.surface === undefined){ -const err36 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "surface"},message:"must have required property '"+"surface"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data17.execution === undefined){ -const err37 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "execution"},message:"must have required property '"+"execution"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data17.permission === undefined){ -const err38 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/required",keyword:"required",params:{missingProperty: "permission"},message:"must have required property '"+"permission"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data17.name !== undefined){ -if(typeof data17.name !== "string"){ -const err39 = {instancePath:instancePath+"/operations/" + i2+"/name",schemaPath:"#/properties/operations/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data17.surface !== undefined){ -if(typeof data17.surface !== "string"){ -const err40 = {instancePath:instancePath+"/operations/" + i2+"/surface",schemaPath:"#/properties/operations/items/properties/surface/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data17.execution !== undefined){ -if(typeof data17.execution !== "string"){ -const err41 = {instancePath:instancePath+"/operations/" + i2+"/execution",schemaPath:"#/properties/operations/items/properties/execution/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data17.permission !== undefined){ -if(typeof data17.permission !== "string"){ -const err42 = {instancePath:instancePath+"/operations/" + i2+"/permission",schemaPath:"#/properties/operations/items/properties/permission/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data17.sensitive !== undefined){ -if(typeof data17.sensitive !== "boolean"){ -const err43 = {instancePath:instancePath+"/operations/" + i2+"/sensitive",schemaPath:"#/properties/operations/items/properties/sensitive/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -else { -const err44 = {instancePath:instancePath+"/operations/" + i2,schemaPath:"#/properties/operations/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -} -if(data.limits !== undefined){ -let data23 = data.limits; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.frame_bytes === undefined){ -const err45 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "frame_bytes"},message:"must have required property '"+"frame_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data23.connections === undefined){ -const err46 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "connections"},message:"must have required property '"+"connections"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data23.in_flight_requests === undefined){ -const err47 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "in_flight_requests"},message:"must have required property '"+"in_flight_requests"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data23.outbound_messages === undefined){ -const err48 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "outbound_messages"},message:"must have required property '"+"outbound_messages"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data23.outbound_bytes === undefined){ -const err49 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "outbound_bytes"},message:"must have required property '"+"outbound_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data23.root_subscriptions === undefined){ -const err50 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "root_subscriptions"},message:"must have required property '"+"root_subscriptions"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data23.content_chunk_bytes === undefined){ -const err51 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "content_chunk_bytes"},message:"must have required property '"+"content_chunk_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data23.upload_bytes === undefined){ -const err52 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/required",keyword:"required",params:{missingProperty: "upload_bytes"},message:"must have required property '"+"upload_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data23.frame_bytes !== undefined){ -let data24 = data23.frame_bytes; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err53 = {instancePath:instancePath+"/limits/frame_bytes",schemaPath:"#/properties/limits/properties/frame_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data23.connections !== undefined){ -let data25 = data23.connections; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err54 = {instancePath:instancePath+"/limits/connections",schemaPath:"#/properties/limits/properties/connections/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data23.in_flight_requests !== undefined){ -let data26 = data23.in_flight_requests; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err55 = {instancePath:instancePath+"/limits/in_flight_requests",schemaPath:"#/properties/limits/properties/in_flight_requests/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data23.outbound_messages !== undefined){ -let data27 = data23.outbound_messages; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err56 = {instancePath:instancePath+"/limits/outbound_messages",schemaPath:"#/properties/limits/properties/outbound_messages/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data23.outbound_bytes !== undefined){ -let data28 = data23.outbound_bytes; -if(typeof data28 === "string"){ -if(!pattern0.test(data28)){ -const err57 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(!(formats0.validate(data28))){ -const err58 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -else { -const err59 = {instancePath:instancePath+"/limits/outbound_bytes",schemaPath:"#/properties/limits/properties/outbound_bytes/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data23.root_subscriptions !== undefined){ -let data29 = data23.root_subscriptions; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err60 = {instancePath:instancePath+"/limits/root_subscriptions",schemaPath:"#/properties/limits/properties/root_subscriptions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data23.content_chunk_bytes !== undefined){ -let data30 = data23.content_chunk_bytes; -if(!((typeof data30 == "number") && (!(data30 % 1) && !isNaN(data30)))){ -const err61 = {instancePath:instancePath+"/limits/content_chunk_bytes",schemaPath:"#/properties/limits/properties/content_chunk_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data23.upload_bytes !== undefined){ -let data31 = data23.upload_bytes; -if(typeof data31 === "string"){ -if(!pattern0.test(data31)){ -const err62 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(!(formats0.validate(data31))){ -const err63 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -else { -const err64 = {instancePath:instancePath+"/limits/upload_bytes",schemaPath:"#/properties/limits/properties/upload_bytes/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -else { -const err65 = {instancePath:instancePath+"/limits",schemaPath:"#/properties/limits/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data.negotiated_capabilities !== undefined){ -let data32 = data.negotiated_capabilities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err66 = {instancePath:instancePath+"/negotiated_capabilities",schemaPath:"#/properties/negotiated_capabilities/type",keyword:"type",params:{type: schema93.properties.negotiated_capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(Array.isArray(data32)){ -const len3 = data32.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data32[i3] !== "string"){ -const err67 = {instancePath:instancePath+"/negotiated_capabilities/" + i3,schemaPath:"#/properties/negotiated_capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -} -if(data.protocol_minor !== undefined){ -let data34 = data.protocol_minor; -if(!((typeof data34 == "number") && (!(data34 % 1) && !isNaN(data34)))){ -const err68 = {instancePath:instancePath+"/protocol_minor",schemaPath:"#/properties/protocol_minor/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data.runtime_id !== undefined){ -if(typeof data.runtime_id !== "string"){ -const err69 = {instancePath:instancePath+"/runtime_id",schemaPath:"#/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data.connection_id !== undefined){ -if(typeof data.connection_id !== "string"){ -const err70 = {instancePath:instancePath+"/connection_id",schemaPath:"#/properties/connection_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.host_platform !== undefined){ -if(typeof data.host_platform !== "string"){ -const err71 = {instancePath:instancePath+"/host_platform",schemaPath:"#/properties/host_platform/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.host_architecture !== undefined){ -if(typeof data.host_architecture !== "string"){ -const err72 = {instancePath:instancePath+"/host_architecture",schemaPath:"#/properties/host_architecture/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data.network_endpoint !== undefined){ -if(typeof data.network_endpoint !== "string"){ -const err73 = {instancePath:instancePath+"/network_endpoint",schemaPath:"#/properties/network_endpoint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.protocol_major !== undefined){ -let data40 = data.protocol_major; -if(!((typeof data40 == "number") && (!(data40 % 1) && !isNaN(data40)))){ -const err74 = {instancePath:instancePath+"/protocol_major",schemaPath:"#/properties/protocol_major/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err75 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.generation !== undefined){ -let data42 = data.generation; -if(typeof data42 === "string"){ -if(!pattern0.test(data42)){ -const err76 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -if(!(formats0.validate(data42))){ -const err77 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -else { -const err78 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -if(data.pid !== undefined){ -let data43 = data.pid; -if(!((typeof data43 == "number") && (!(data43 % 1) && !isNaN(data43)))){ -const err79 = {instancePath:instancePath+"/pid",schemaPath:"#/properties/pid/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -if(data.started_at !== undefined){ -if(typeof data.started_at !== "string"){ -const err80 = {instancePath:instancePath+"/started_at",schemaPath:"#/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data45 = data.capabilities; -if((data45 !== null) && (!(Array.isArray(data45)))){ -const err81 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema93.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(Array.isArray(data45)){ -const len4 = data45.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data45[i4] !== "string"){ -const err82 = {instancePath:instancePath+"/capabilities/" + i4,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -} -} -} -} -else { -const err83 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -validate92.errors = vErrors; -return errors === 0; -} - -export const LSPListResult = validate93; -const schema94 = {"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"root":{"type":"string"},"state":{"type":"string"},"error":{"type":"string"}},"required":["name","state"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/LSPListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"LSPListResult"}; - -function validate93(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/LSPListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema94.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.name === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.state === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err3 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.root !== undefined){ -if(typeof data0.root !== "string"){ -const err4 = {instancePath:instancePath+"/" + i0+"/root",schemaPath:"#/items/properties/root/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.state !== undefined){ -if(typeof data0.state !== "string"){ -const err5 = {instancePath:instancePath+"/" + i0+"/state",schemaPath:"#/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.error !== undefined){ -if(typeof data0.error !== "string"){ -const err6 = {instancePath:instancePath+"/" + i0+"/error",schemaPath:"#/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -validate93.errors = vErrors; -return errors === 0; -} - -export const LifecycleEvent = validate94; -const schema95 = {"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":true},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":true}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":true}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/LifecycleEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"LifecycleEvent","additionalProperties":true}; - -function validate94(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/LifecycleEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err0 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err2 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.sender_agent_id !== undefined){ -if(typeof data.sender_agent_id !== "string"){ -const err3 = {instancePath:instancePath+"/sender_agent_id",schemaPath:"#/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.inbox_seq !== undefined){ -let data4 = data.inbox_seq; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err4 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err5 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/inbox_seq",schemaPath:"#/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.inbox_kind !== undefined){ -if(typeof data.inbox_kind !== "string"){ -const err7 = {instancePath:instancePath+"/inbox_kind",schemaPath:"#/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err8 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.message_id !== undefined){ -if(typeof data.message_id !== "string"){ -const err9 = {instancePath:instancePath+"/message_id",schemaPath:"#/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.phase !== undefined){ -if(typeof data.phase !== "string"){ -const err10 = {instancePath:instancePath+"/phase",schemaPath:"#/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err11 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.terminal_cause !== undefined){ -if(typeof data.terminal_cause !== "string"){ -const err12 = {instancePath:instancePath+"/terminal_cause",schemaPath:"#/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.command_client_id !== undefined){ -if(typeof data.command_client_id !== "string"){ -const err13 = {instancePath:instancePath+"/command_client_id",schemaPath:"#/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err14 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err15 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err16 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.schedule_id !== undefined){ -let data15 = data.schedule_id; -if(!((typeof data15 == "number") && (!(data15 % 1) && !isNaN(data15)))){ -const err17 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.slot !== undefined){ -if(typeof data.slot !== "string"){ -const err18 = {instancePath:instancePath+"/slot",schemaPath:"#/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err19 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.model_call !== undefined){ -let data18 = data.model_call; -if((data18 !== null) && (!(data18 && typeof data18 == "object" && !Array.isArray(data18)))){ -const err20 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/type",keyword:"type",params:{type: schema95.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -if(data18.id === undefined){ -const err21 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data18.logical_id === undefined){ -const err22 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data18.number === undefined){ -const err23 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data18.purpose === undefined){ -const err24 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data18.usage_source === undefined){ -const err25 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data18.cost_source === undefined){ -const err26 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data18.tokens === undefined){ -const err27 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data18.cost_micros === undefined){ -const err28 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data18.elapsed_millis === undefined){ -const err29 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data18.exhausted === undefined){ -const err30 = {instancePath:instancePath+"/model_call",schemaPath:"#/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data18.id !== undefined){ -if(typeof data18.id !== "string"){ -const err31 = {instancePath:instancePath+"/model_call/id",schemaPath:"#/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data18.logical_id !== undefined){ -if(typeof data18.logical_id !== "string"){ -const err32 = {instancePath:instancePath+"/model_call/logical_id",schemaPath:"#/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data18.number !== undefined){ -let data21 = data18.number; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err33 = {instancePath:instancePath+"/model_call/number",schemaPath:"#/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data18.purpose !== undefined){ -if(typeof data18.purpose !== "string"){ -const err34 = {instancePath:instancePath+"/model_call/purpose",schemaPath:"#/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data18.usage_source !== undefined){ -if(typeof data18.usage_source !== "string"){ -const err35 = {instancePath:instancePath+"/model_call/usage_source",schemaPath:"#/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data18.cost_source !== undefined){ -if(typeof data18.cost_source !== "string"){ -const err36 = {instancePath:instancePath+"/model_call/cost_source",schemaPath:"#/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data18.tokens !== undefined){ -let data25 = data18.tokens; -if(typeof data25 === "string"){ -if(!pattern0.test(data25)){ -const err37 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(!(formats0.validate(data25))){ -const err38 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -else { -const err39 = {instancePath:instancePath+"/model_call/tokens",schemaPath:"#/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data18.cost_micros !== undefined){ -let data26 = data18.cost_micros; -if(typeof data26 === "string"){ -if(!pattern0.test(data26)){ -const err40 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data26))){ -const err41 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/model_call/cost_micros",schemaPath:"#/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data18.elapsed_millis !== undefined){ -let data27 = data18.elapsed_millis; -if(typeof data27 === "string"){ -if(!pattern0.test(data27)){ -const err43 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(!(formats0.validate(data27))){ -const err44 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -else { -const err45 = {instancePath:instancePath+"/model_call/elapsed_millis",schemaPath:"#/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data18.exhausted !== undefined){ -if(typeof data18.exhausted !== "boolean"){ -const err46 = {instancePath:instancePath+"/model_call/exhausted",schemaPath:"#/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -} -if(data.acknowledged_inbox !== undefined){ -let data29 = data.acknowledged_inbox; -if(Array.isArray(data29)){ -const len0 = data29.length; -for(let i0=0; i0<len0; i0++){ -let data30 = data29[i0]; -if(typeof data30 === "string"){ -if(!pattern0.test(data30)){ -const err47 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(!(formats0.validate(data30))){ -const err48 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -else { -const err49 = {instancePath:instancePath+"/acknowledged_inbox/" + i0,schemaPath:"#/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -} -else { -const err50 = {instancePath:instancePath+"/acknowledged_inbox",schemaPath:"#/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err51 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err52 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data.version !== undefined){ -let data33 = data.version; -if(typeof data33 === "string"){ -if(!pattern0.test(data33)){ -const err53 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(!(formats0.validate(data33))){ -const err54 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -else { -const err55 = {instancePath:instancePath+"/version",schemaPath:"#/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data.expected_version !== undefined){ -let data34 = data.expected_version; -if(typeof data34 === "string"){ -if(!pattern0.test(data34)){ -const err56 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(!(formats0.validate(data34))){ -const err57 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -else { -const err58 = {instancePath:instancePath+"/expected_version",schemaPath:"#/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data.restored !== undefined){ -let data35 = data.restored; -if((data35 !== null) && (!(Array.isArray(data35)))){ -const err59 = {instancePath:instancePath+"/restored",schemaPath:"#/properties/restored/type",keyword:"type",params:{type: schema95.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(Array.isArray(data35)){ -const len1 = data35.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data35[i1] !== "string"){ -const err60 = {instancePath:instancePath+"/restored/" + i1,schemaPath:"#/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -} -} -if(data.not_restored !== undefined){ -let data37 = data.not_restored; -if((data37 !== null) && (!(Array.isArray(data37)))){ -const err61 = {instancePath:instancePath+"/not_restored",schemaPath:"#/properties/not_restored/type",keyword:"type",params:{type: schema95.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -if(Array.isArray(data37)){ -const len2 = data37.length; -for(let i2=0; i2<len2; i2++){ -let data38 = data37[i2]; -if(data38 && typeof data38 == "object" && !Array.isArray(data38)){ -if(data38.name === undefined){ -const err62 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data38.reason === undefined){ -const err63 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data38.name !== undefined){ -if(typeof data38.name !== "string"){ -const err64 = {instancePath:instancePath+"/not_restored/" + i2+"/name",schemaPath:"#/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data38.reason !== undefined){ -if(typeof data38.reason !== "string"){ -const err65 = {instancePath:instancePath+"/not_restored/" + i2+"/reason",schemaPath:"#/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -} -else { -const err66 = {instancePath:instancePath+"/not_restored/" + i2,schemaPath:"#/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -} -} -if(data.attempt !== undefined){ -if(typeof data.attempt !== "string"){ -const err67 = {instancePath:instancePath+"/attempt",schemaPath:"#/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data.budget_kind !== undefined){ -if(typeof data.budget_kind !== "string"){ -const err68 = {instancePath:instancePath+"/budget_kind",schemaPath:"#/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data.amount !== undefined){ -let data43 = data.amount; -if(typeof data43 === "string"){ -if(!pattern0.test(data43)){ -const err69 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(!(formats0.validate(data43))){ -const err70 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -else { -const err71 = {instancePath:instancePath+"/amount",schemaPath:"#/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.limit !== undefined){ -let data44 = data.limit; -if(typeof data44 === "string"){ -if(!pattern0.test(data44)){ -const err72 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -if(!(formats0.validate(data44))){ -const err73 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -else { -const err74 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.used !== undefined){ -let data45 = data.used; -if(typeof data45 === "string"){ -if(!pattern0.test(data45)){ -const err75 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -if(!(formats0.validate(data45))){ -const err76 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -else { -const err77 = {instancePath:instancePath+"/used",schemaPath:"#/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.reserved !== undefined){ -let data46 = data.reserved; -if(typeof data46 === "string"){ -if(!pattern0.test(data46)){ -const err78 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(!(formats0.validate(data46))){ -const err79 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -} -else { -const err80 = {instancePath:instancePath+"/reserved",schemaPath:"#/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data.capability_id !== undefined){ -if(typeof data.capability_id !== "string"){ -const err81 = {instancePath:instancePath+"/capability_id",schemaPath:"#/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data.generation !== undefined){ -let data48 = data.generation; -if(typeof data48 === "string"){ -if(!pattern0.test(data48)){ -const err82 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(!(formats0.validate(data48))){ -const err83 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -} -else { -const err84 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -} -if(data.permission_id !== undefined){ -if(typeof data.permission_id !== "string"){ -const err85 = {instancePath:instancePath+"/permission_id",schemaPath:"#/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err86 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data.canonical_path !== undefined){ -if(typeof data.canonical_path !== "string"){ -const err87 = {instancePath:instancePath+"/canonical_path",schemaPath:"#/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data.request_digest !== undefined){ -if(typeof data.request_digest !== "string"){ -const err88 = {instancePath:instancePath+"/request_digest",schemaPath:"#/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data.command !== undefined){ -if(typeof data.command !== "string"){ -const err89 = {instancePath:instancePath+"/command",schemaPath:"#/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data.rule !== undefined){ -if(typeof data.rule !== "string"){ -const err90 = {instancePath:instancePath+"/rule",schemaPath:"#/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data.rule_source !== undefined){ -if(typeof data.rule_source !== "string"){ -const err91 = {instancePath:instancePath+"/rule_source",schemaPath:"#/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data.question_id !== undefined){ -if(typeof data.question_id !== "string"){ -const err92 = {instancePath:instancePath+"/question_id",schemaPath:"#/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data.question !== undefined){ -if(typeof data.question !== "string"){ -const err93 = {instancePath:instancePath+"/question",schemaPath:"#/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data.options !== undefined){ -let data58 = data.options; -if((data58 !== null) && (!(Array.isArray(data58)))){ -const err94 = {instancePath:instancePath+"/options",schemaPath:"#/properties/options/type",keyword:"type",params:{type: schema95.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(Array.isArray(data58)){ -const len3 = data58.length; -for(let i3=0; i3<len3; i3++){ -let data59 = data58[i3]; -if(data59 && typeof data59 == "object" && !Array.isArray(data59)){ -if(data59.label === undefined){ -const err95 = {instancePath:instancePath+"/options/" + i3,schemaPath:"#/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -if(data59.label !== undefined){ -if(typeof data59.label !== "string"){ -const err96 = {instancePath:instancePath+"/options/" + i3+"/label",schemaPath:"#/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data59.description !== undefined){ -if(typeof data59.description !== "string"){ -const err97 = {instancePath:instancePath+"/options/" + i3+"/description",schemaPath:"#/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data59.recommended !== undefined){ -if(typeof data59.recommended !== "boolean"){ -const err98 = {instancePath:instancePath+"/options/" + i3+"/recommended",schemaPath:"#/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -} -else { -const err99 = {instancePath:instancePath+"/options/" + i3,schemaPath:"#/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -} -} -if(data.multiple !== undefined){ -if(typeof data.multiple !== "boolean"){ -const err100 = {instancePath:instancePath+"/multiple",schemaPath:"#/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data.questions !== undefined){ -let data64 = data.questions; -if((data64 !== null) && (!(Array.isArray(data64)))){ -const err101 = {instancePath:instancePath+"/questions",schemaPath:"#/properties/questions/type",keyword:"type",params:{type: schema95.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(Array.isArray(data64)){ -const len4 = data64.length; -for(let i4=0; i4<len4; i4++){ -let data65 = data64[i4]; -if(data65 && typeof data65 == "object" && !Array.isArray(data65)){ -if(data65.question === undefined){ -const err102 = {instancePath:instancePath+"/questions/" + i4,schemaPath:"#/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(data65.question !== undefined){ -if(typeof data65.question !== "string"){ -const err103 = {instancePath:instancePath+"/questions/" + i4+"/question",schemaPath:"#/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data65.options !== undefined){ -let data67 = data65.options; -if((data67 !== null) && (!(Array.isArray(data67)))){ -const err104 = {instancePath:instancePath+"/questions/" + i4+"/options",schemaPath:"#/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema95.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -if(Array.isArray(data67)){ -const len5 = data67.length; -for(let i5=0; i5<len5; i5++){ -let data68 = data67[i5]; -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -if(data68.label === undefined){ -const err105 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5,schemaPath:"#/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -if(data68.label !== undefined){ -if(typeof data68.label !== "string"){ -const err106 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/label",schemaPath:"#/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data68.description !== undefined){ -if(typeof data68.description !== "string"){ -const err107 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/description",schemaPath:"#/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data68.recommended !== undefined){ -if(typeof data68.recommended !== "boolean"){ -const err108 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5+"/recommended",schemaPath:"#/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -} -else { -const err109 = {instancePath:instancePath+"/questions/" + i4+"/options/" + i5,schemaPath:"#/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -} -} -if(data65.multiple !== undefined){ -if(typeof data65.multiple !== "boolean"){ -const err110 = {instancePath:instancePath+"/questions/" + i4+"/multiple",schemaPath:"#/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -} -else { -const err111 = {instancePath:instancePath+"/questions/" + i4,schemaPath:"#/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -} -} -} -if(data.answer !== undefined){ -let data73 = data.answer; -if((data73 !== null) && (!(Array.isArray(data73)))){ -const err112 = {instancePath:instancePath+"/answer",schemaPath:"#/properties/answer/type",keyword:"type",params:{type: schema95.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -if(Array.isArray(data73)){ -const len6 = data73.length; -for(let i6=0; i6<len6; i6++){ -if(typeof data73[i6] !== "string"){ -const err113 = {instancePath:instancePath+"/answer/" + i6,schemaPath:"#/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -} -} -} -if(data.dismissed !== undefined){ -if(typeof data.dismissed !== "boolean"){ -const err114 = {instancePath:instancePath+"/dismissed",schemaPath:"#/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data.answers !== undefined){ -let data76 = data.answers; -if((data76 !== null) && (!(Array.isArray(data76)))){ -const err115 = {instancePath:instancePath+"/answers",schemaPath:"#/properties/answers/type",keyword:"type",params:{type: schema95.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -if(Array.isArray(data76)){ -const len7 = data76.length; -for(let i7=0; i7<len7; i7++){ -let data77 = data76[i7]; -if(data77 && typeof data77 == "object" && !Array.isArray(data77)){ -if(data77.answer !== undefined){ -let data78 = data77.answer; -if((data78 !== null) && (!(Array.isArray(data78)))){ -const err116 = {instancePath:instancePath+"/answers/" + i7+"/answer",schemaPath:"#/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema95.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -if(Array.isArray(data78)){ -const len8 = data78.length; -for(let i8=0; i8<len8; i8++){ -if(typeof data78[i8] !== "string"){ -const err117 = {instancePath:instancePath+"/answers/" + i7+"/answer/" + i8,schemaPath:"#/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -} -} -if(data77.dismissed !== undefined){ -if(typeof data77.dismissed !== "boolean"){ -const err118 = {instancePath:instancePath+"/answers/" + i7+"/dismissed",schemaPath:"#/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -} -else { -const err119 = {instancePath:instancePath+"/answers/" + i7,schemaPath:"#/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -} -} -} -else { -const err120 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -validate94.errors = vErrors; -return errors === 0; -} - -export const ListParams = validate95; -const schema96 = {"type":"object","properties":{"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ListParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ListParams","additionalProperties":true}; - -function validate95(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ListParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit !== undefined){ -let data0 = data.limit; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err0 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate95.errors = vErrors; -return errors === 0; -} - -export const MCPAttachParams = validate96; -const schema97 = {"type":"object","properties":{"servers":{"type":"object","additionalProperties":{"type":"object","properties":{"command":{"type":["null","array"],"items":{"type":"string"}},"env":{"type":"object","additionalProperties":{"type":"string"}},"cwd":{"type":"string"},"url":{"type":"string"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"enabled":{"type":["null","boolean"]},"note":{"type":"string"},"startup_timeout":{"type":"integer"},"tool_timeout":{"type":"integer"},"source":{"type":"string"},"origin":{"type":"string"}},"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/MCPAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPAttachParams","required":["servers"],"additionalProperties":true}; - -function validate96(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPAttachParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.servers === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.servers !== undefined){ -let data0 = data.servers; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key0 in data0){ -let data1 = data0[key0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.command !== undefined){ -let data2 = data1.command; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err1 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/command",schemaPath:"#/properties/servers/additionalProperties/properties/command/type",keyword:"type",params:{type: schema97.properties.servers.additionalProperties.properties.command.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data2)){ -const len0 = data2.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data2[i0] !== "string"){ -const err2 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/command/" + i0,schemaPath:"#/properties/servers/additionalProperties/properties/command/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -} -if(data1.env !== undefined){ -let data4 = data1.env; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -for(const key1 in data4){ -if(typeof data4[key1] !== "string"){ -const err3 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/env/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/properties/env/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/env",schemaPath:"#/properties/servers/additionalProperties/properties/env/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.cwd !== undefined){ -if(typeof data1.cwd !== "string"){ -const err5 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/cwd",schemaPath:"#/properties/servers/additionalProperties/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.url !== undefined){ -if(typeof data1.url !== "string"){ -const err6 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/url",schemaPath:"#/properties/servers/additionalProperties/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.headers !== undefined){ -let data8 = data1.headers; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -for(const key2 in data8){ -if(typeof data8[key2] !== "string"){ -const err7 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/headers/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/properties/headers/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/headers",schemaPath:"#/properties/servers/additionalProperties/properties/headers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.enabled !== undefined){ -let data10 = data1.enabled; -if((data10 !== null) && (typeof data10 !== "boolean")){ -const err9 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/enabled",schemaPath:"#/properties/servers/additionalProperties/properties/enabled/type",keyword:"type",params:{type: schema97.properties.servers.additionalProperties.properties.enabled.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.note !== undefined){ -if(typeof data1.note !== "string"){ -const err10 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/note",schemaPath:"#/properties/servers/additionalProperties/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.startup_timeout !== undefined){ -let data12 = data1.startup_timeout; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err11 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/startup_timeout",schemaPath:"#/properties/servers/additionalProperties/properties/startup_timeout/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.tool_timeout !== undefined){ -let data13 = data1.tool_timeout; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err12 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/tool_timeout",schemaPath:"#/properties/servers/additionalProperties/properties/tool_timeout/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err13 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/source",schemaPath:"#/properties/servers/additionalProperties/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.origin !== undefined){ -if(typeof data1.origin !== "string"){ -const err14 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/origin",schemaPath:"#/properties/servers/additionalProperties/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/servers/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/servers/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath:instancePath+"/servers",schemaPath:"#/properties/servers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate96.errors = vErrors; -return errors === 0; -} - -export const MCPBrandIconsParams = validate97; -const schema98 = {"type":"object","properties":{"keys":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPBrandIconsParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPBrandIconsParams","required":["keys"],"additionalProperties":true}; - -function validate97(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPBrandIconsParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.keys === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "keys"},message:"must have required property '"+"keys"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.keys !== undefined){ -let data0 = data.keys; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/keys",schemaPath:"#/properties/keys/type",keyword:"type",params:{type: schema98.properties.keys.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err2 = {instancePath:instancePath+"/keys/" + i0,schemaPath:"#/properties/keys/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate97.errors = vErrors; -return errors === 0; -} - -export const MCPBrandIconsResult = validate98; -const schema99 = {"type":"object","properties":{"icons":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPBrandIconsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPBrandIconsResult","required":["icons"],"additionalProperties":true}; - -function validate98(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPBrandIconsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.icons === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "icons"},message:"must have required property '"+"icons"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.icons !== undefined){ -let data0 = data.icons; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key0 in data0){ -if(typeof data0[key0] !== "string"){ -const err1 = {instancePath:instancePath+"/icons/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/icons/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath:instancePath+"/icons",schemaPath:"#/properties/icons/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate98.errors = vErrors; -return errors === 0; -} - -export const MCPImportApplyParams = validate99; -const schema100 = {"type":"object","properties":{"cwd":{"type":"string"},"names":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportApplyParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportApplyParams","required":["names"],"additionalProperties":true}; - -function validate99(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportApplyParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.names === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "names"},message:"must have required property '"+"names"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err1 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.names !== undefined){ -let data1 = data.names; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err2 = {instancePath:instancePath+"/names",schemaPath:"#/properties/names/type",keyword:"type",params:{type: schema100.properties.names.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err3 = {instancePath:instancePath+"/names/" + i0,schemaPath:"#/properties/names/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate99.errors = vErrors; -return errors === 0; -} - -export const MCPImportApplyResult = validate100; -const schema101 = {"type":"object","properties":{"imported":{"type":["null","array"],"items":{"type":"string"}},"skipped":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportApplyResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportApplyResult","required":["imported"],"additionalProperties":true}; - -function validate100(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportApplyResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.imported === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "imported"},message:"must have required property '"+"imported"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.imported !== undefined){ -let data0 = data.imported; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/imported",schemaPath:"#/properties/imported/type",keyword:"type",params:{type: schema101.properties.imported.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err2 = {instancePath:instancePath+"/imported/" + i0,schemaPath:"#/properties/imported/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -} -if(data.skipped !== undefined){ -let data2 = data.skipped; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -for(const key0 in data2){ -if(typeof data2[key0] !== "string"){ -const err3 = {instancePath:instancePath+"/skipped/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/skipped/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath:instancePath+"/skipped",schemaPath:"#/properties/skipped/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate100.errors = vErrors; -return errors === 0; -} - -export const MCPImportCandidatesParams = validate101; -const schema102 = {"type":"object","properties":{"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MCPImportCandidatesParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportCandidatesParams","additionalProperties":true}; - -function validate101(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportCandidatesParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err0 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate101.errors = vErrors; -return errors === 0; -} - -export const MCPImportCandidatesResult = validate102; -const schema103 = {"type":"object","properties":{"candidates":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"source":{"type":"string"},"state":{"type":"string"},"note":{"type":"string"},"brand_hint":{"type":"string"},"brand_key":{"type":"string"}},"required":["name","source","state"],"additionalProperties":true}},"offered":{"type":"boolean"},"config_path":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/MCPImportCandidatesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportCandidatesResult","required":["candidates","offered","config_path"],"additionalProperties":true}; - -function validate102(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportCandidatesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.candidates === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "candidates"},message:"must have required property '"+"candidates"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.offered === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offered"},message:"must have required property '"+"offered"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.config_path === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "config_path"},message:"must have required property '"+"config_path"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.candidates !== undefined){ -let data0 = data.candidates; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err3 = {instancePath:instancePath+"/candidates",schemaPath:"#/properties/candidates/type",keyword:"type",params:{type: schema103.properties.candidates.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.name === undefined){ -const err4 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.source === undefined){ -const err5 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.state === undefined){ -const err6 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err7 = {instancePath:instancePath+"/candidates/" + i0+"/name",schemaPath:"#/properties/candidates/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.source !== undefined){ -if(typeof data1.source !== "string"){ -const err8 = {instancePath:instancePath+"/candidates/" + i0+"/source",schemaPath:"#/properties/candidates/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.state !== undefined){ -if(typeof data1.state !== "string"){ -const err9 = {instancePath:instancePath+"/candidates/" + i0+"/state",schemaPath:"#/properties/candidates/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.note !== undefined){ -if(typeof data1.note !== "string"){ -const err10 = {instancePath:instancePath+"/candidates/" + i0+"/note",schemaPath:"#/properties/candidates/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.brand_hint !== undefined){ -if(typeof data1.brand_hint !== "string"){ -const err11 = {instancePath:instancePath+"/candidates/" + i0+"/brand_hint",schemaPath:"#/properties/candidates/items/properties/brand_hint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.brand_key !== undefined){ -if(typeof data1.brand_key !== "string"){ -const err12 = {instancePath:instancePath+"/candidates/" + i0+"/brand_key",schemaPath:"#/properties/candidates/items/properties/brand_key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath:instancePath+"/candidates/" + i0,schemaPath:"#/properties/candidates/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -} -if(data.offered !== undefined){ -if(typeof data.offered !== "boolean"){ -const err14 = {instancePath:instancePath+"/offered",schemaPath:"#/properties/offered/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.config_path !== undefined){ -if(typeof data.config_path !== "string"){ -const err15 = {instancePath:instancePath+"/config_path",schemaPath:"#/properties/config_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.errors !== undefined){ -let data10 = data.errors; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -for(const key0 in data10){ -if(typeof data10[key0] !== "string"){ -const err16 = {instancePath:instancePath+"/errors/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/errors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -validate102.errors = vErrors; -return errors === 0; -} - -export const MCPImportParams = validate103; -const schema104 = {"type":"object","properties":{"source":{"type":"string"},"enabled":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MCPImportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportParams","required":["source","enabled"],"additionalProperties":true}; - -function validate103(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.source === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.enabled === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "enabled"},message:"must have required property '"+"enabled"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err2 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.enabled !== undefined){ -if(typeof data.enabled !== "boolean"){ -const err3 = {instancePath:instancePath+"/enabled",schemaPath:"#/properties/enabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate103.errors = vErrors; -return errors === 0; -} - -export const MCPImportStatusResult = validate104; -const schema105 = {"type":"object","properties":{"claude":{"type":"boolean"},"codex":{"type":"boolean"},"project":{"type":"boolean"},"opencode":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MCPImportStatusResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPImportStatusResult","required":["claude","codex","project","opencode"],"additionalProperties":true}; - -function validate104(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPImportStatusResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.claude === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "claude"},message:"must have required property '"+"claude"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.codex === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "codex"},message:"must have required property '"+"codex"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.project === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "project"},message:"must have required property '"+"project"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.opencode === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "opencode"},message:"must have required property '"+"opencode"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.claude !== undefined){ -if(typeof data.claude !== "boolean"){ -const err4 = {instancePath:instancePath+"/claude",schemaPath:"#/properties/claude/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.codex !== undefined){ -if(typeof data.codex !== "boolean"){ -const err5 = {instancePath:instancePath+"/codex",schemaPath:"#/properties/codex/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.project !== undefined){ -if(typeof data.project !== "boolean"){ -const err6 = {instancePath:instancePath+"/project",schemaPath:"#/properties/project/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.opencode !== undefined){ -if(typeof data.opencode !== "boolean"){ -const err7 = {instancePath:instancePath+"/opencode",schemaPath:"#/properties/opencode/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate104.errors = vErrors; -return errors === 0; -} - -export const MCPListResult = validate105; -const schema106 = {"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/MCPListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPListResult"}; - -function validate105(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema106.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.name === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.status === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.name !== undefined){ -if(typeof data0.name !== "string"){ -const err3 = {instancePath:instancePath+"/" + i0+"/name",schemaPath:"#/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.status !== undefined){ -if(typeof data0.status !== "string"){ -const err4 = {instancePath:instancePath+"/" + i0+"/status",schemaPath:"#/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.note !== undefined){ -if(typeof data0.note !== "string"){ -const err5 = {instancePath:instancePath+"/" + i0+"/note",schemaPath:"#/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.error !== undefined){ -if(typeof data0.error !== "string"){ -const err6 = {instancePath:instancePath+"/" + i0+"/error",schemaPath:"#/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.tools !== undefined){ -let data5 = data0.tools; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err7 = {instancePath:instancePath+"/" + i0+"/tools",schemaPath:"#/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err8 = {instancePath:instancePath+"/" + i0+"/source",schemaPath:"#/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -validate105.errors = vErrors; -return errors === 0; -} - -export const MCPRefreshResult = validate106; -const schema107 = {"type":"object","properties":{"added":{"type":["null","array"],"items":{"type":"string"}},"existing":{"type":["null","array"],"items":{"type":"string"}},"changed":{"type":["null","array"],"items":{"type":"string"}},"servers":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":true}},"blocked":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":true}},"source_errors":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string"},"note":{"type":"string"},"error":{"type":"string"},"tools":{"type":"integer"},"source":{"type":"string"}},"required":["name","status"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/MCPRefreshResult","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPRefreshResult","required":["added","existing","changed","servers","blocked","source_errors"],"additionalProperties":true}; - -function validate106(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPRefreshResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.added === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "added"},message:"must have required property '"+"added"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.existing === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "existing"},message:"must have required property '"+"existing"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.changed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "changed"},message:"must have required property '"+"changed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.servers === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "servers"},message:"must have required property '"+"servers"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.blocked === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "blocked"},message:"must have required property '"+"blocked"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.source_errors === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "source_errors"},message:"must have required property '"+"source_errors"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.added !== undefined){ -let data0 = data.added; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err6 = {instancePath:instancePath+"/added",schemaPath:"#/properties/added/type",keyword:"type",params:{type: schema107.properties.added.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data0[i0] !== "string"){ -const err7 = {instancePath:instancePath+"/added/" + i0,schemaPath:"#/properties/added/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -} -if(data.existing !== undefined){ -let data2 = data.existing; -if((data2 !== null) && (!(Array.isArray(data2)))){ -const err8 = {instancePath:instancePath+"/existing",schemaPath:"#/properties/existing/type",keyword:"type",params:{type: schema107.properties.existing.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data2)){ -const len1 = data2.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data2[i1] !== "string"){ -const err9 = {instancePath:instancePath+"/existing/" + i1,schemaPath:"#/properties/existing/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data.changed !== undefined){ -let data4 = data.changed; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err10 = {instancePath:instancePath+"/changed",schemaPath:"#/properties/changed/type",keyword:"type",params:{type: schema107.properties.changed.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(Array.isArray(data4)){ -const len2 = data4.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data4[i2] !== "string"){ -const err11 = {instancePath:instancePath+"/changed/" + i2,schemaPath:"#/properties/changed/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -if(data.servers !== undefined){ -let data6 = data.servers; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err12 = {instancePath:instancePath+"/servers",schemaPath:"#/properties/servers/type",keyword:"type",params:{type: schema107.properties.servers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(Array.isArray(data6)){ -const len3 = data6.length; -for(let i3=0; i3<len3; i3++){ -let data7 = data6[i3]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.name === undefined){ -const err13 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.status === undefined){ -const err14 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.name !== undefined){ -if(typeof data7.name !== "string"){ -const err15 = {instancePath:instancePath+"/servers/" + i3+"/name",schemaPath:"#/properties/servers/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data7.status !== undefined){ -if(typeof data7.status !== "string"){ -const err16 = {instancePath:instancePath+"/servers/" + i3+"/status",schemaPath:"#/properties/servers/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data7.note !== undefined){ -if(typeof data7.note !== "string"){ -const err17 = {instancePath:instancePath+"/servers/" + i3+"/note",schemaPath:"#/properties/servers/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data7.error !== undefined){ -if(typeof data7.error !== "string"){ -const err18 = {instancePath:instancePath+"/servers/" + i3+"/error",schemaPath:"#/properties/servers/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data7.tools !== undefined){ -let data12 = data7.tools; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err19 = {instancePath:instancePath+"/servers/" + i3+"/tools",schemaPath:"#/properties/servers/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data7.source !== undefined){ -if(typeof data7.source !== "string"){ -const err20 = {instancePath:instancePath+"/servers/" + i3+"/source",schemaPath:"#/properties/servers/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath:instancePath+"/servers/" + i3,schemaPath:"#/properties/servers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data.blocked !== undefined){ -let data14 = data.blocked; -if((data14 !== null) && (!(Array.isArray(data14)))){ -const err22 = {instancePath:instancePath+"/blocked",schemaPath:"#/properties/blocked/type",keyword:"type",params:{type: schema107.properties.blocked.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data14)){ -const len4 = data14.length; -for(let i4=0; i4<len4; i4++){ -let data15 = data14[i4]; -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.name === undefined){ -const err23 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data15.status === undefined){ -const err24 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data15.name !== undefined){ -if(typeof data15.name !== "string"){ -const err25 = {instancePath:instancePath+"/blocked/" + i4+"/name",schemaPath:"#/properties/blocked/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data15.status !== undefined){ -if(typeof data15.status !== "string"){ -const err26 = {instancePath:instancePath+"/blocked/" + i4+"/status",schemaPath:"#/properties/blocked/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data15.note !== undefined){ -if(typeof data15.note !== "string"){ -const err27 = {instancePath:instancePath+"/blocked/" + i4+"/note",schemaPath:"#/properties/blocked/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data15.error !== undefined){ -if(typeof data15.error !== "string"){ -const err28 = {instancePath:instancePath+"/blocked/" + i4+"/error",schemaPath:"#/properties/blocked/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data15.tools !== undefined){ -let data20 = data15.tools; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err29 = {instancePath:instancePath+"/blocked/" + i4+"/tools",schemaPath:"#/properties/blocked/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data15.source !== undefined){ -if(typeof data15.source !== "string"){ -const err30 = {instancePath:instancePath+"/blocked/" + i4+"/source",schemaPath:"#/properties/blocked/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -else { -const err31 = {instancePath:instancePath+"/blocked/" + i4,schemaPath:"#/properties/blocked/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -} -if(data.source_errors !== undefined){ -let data22 = data.source_errors; -if((data22 !== null) && (!(Array.isArray(data22)))){ -const err32 = {instancePath:instancePath+"/source_errors",schemaPath:"#/properties/source_errors/type",keyword:"type",params:{type: schema107.properties.source_errors.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(Array.isArray(data22)){ -const len5 = data22.length; -for(let i5=0; i5<len5; i5++){ -let data23 = data22[i5]; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.name === undefined){ -const err33 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data23.status === undefined){ -const err34 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data23.name !== undefined){ -if(typeof data23.name !== "string"){ -const err35 = {instancePath:instancePath+"/source_errors/" + i5+"/name",schemaPath:"#/properties/source_errors/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data23.status !== undefined){ -if(typeof data23.status !== "string"){ -const err36 = {instancePath:instancePath+"/source_errors/" + i5+"/status",schemaPath:"#/properties/source_errors/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data23.note !== undefined){ -if(typeof data23.note !== "string"){ -const err37 = {instancePath:instancePath+"/source_errors/" + i5+"/note",schemaPath:"#/properties/source_errors/items/properties/note/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data23.error !== undefined){ -if(typeof data23.error !== "string"){ -const err38 = {instancePath:instancePath+"/source_errors/" + i5+"/error",schemaPath:"#/properties/source_errors/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data23.tools !== undefined){ -let data28 = data23.tools; -if(!((typeof data28 == "number") && (!(data28 % 1) && !isNaN(data28)))){ -const err39 = {instancePath:instancePath+"/source_errors/" + i5+"/tools",schemaPath:"#/properties/source_errors/items/properties/tools/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data23.source !== undefined){ -if(typeof data23.source !== "string"){ -const err40 = {instancePath:instancePath+"/source_errors/" + i5+"/source",schemaPath:"#/properties/source_errors/items/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -} -else { -const err41 = {instancePath:instancePath+"/source_errors/" + i5,schemaPath:"#/properties/source_errors/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -} -} -else { -const err42 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -validate106.errors = vErrors; -return errors === 0; -} - -export const MCPServerParams = validate107; -const schema108 = {"type":"object","properties":{"name":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MCPServerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MCPServerParams","required":["name"],"additionalProperties":true}; - -function validate107(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MCPServerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.name === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err1 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate107.errors = vErrors; -return errors === 0; -} - -export const MailboxInspection = validate108; -const schema109 = {"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"sender":{"type":"string"},"recipient":{"type":"string"},"kind":{"type":"string"},"delivery":{"type":"string"},"subject":{"type":"string"},"excerpt":{"type":"string"},"body":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"evidence_handle":{"type":"string"},"status":{"type":"string"},"available_at":{"type":"string"},"created_at":{"type":"string"},"delivered_at":{"type":"string"},"delivered_turn_id":{"type":"string"},"done_at":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MailboxInspection","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxInspection","required":["id","revision","sender","recipient","kind","delivery","subject","excerpt","body","status","available_at","created_at","delivered_at","done_at"],"additionalProperties":true}; - -function validate108(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxInspection" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.sender === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "sender"},message:"must have required property '"+"sender"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.recipient === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "recipient"},message:"must have required property '"+"recipient"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.kind === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.delivery === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "delivery"},message:"must have required property '"+"delivery"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.subject === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subject"},message:"must have required property '"+"subject"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.excerpt === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "excerpt"},message:"must have required property '"+"excerpt"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.body === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.status === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.available_at === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "available_at"},message:"must have required property '"+"available_at"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.created_at === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.delivered_at === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "delivered_at"},message:"must have required property '"+"delivered_at"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.done_at === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "done_at"},message:"must have required property '"+"done_at"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err14 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.revision !== undefined){ -let data1 = data.revision; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err15 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err16 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -else { -const err17 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.sender !== undefined){ -if(typeof data.sender !== "string"){ -const err18 = {instancePath:instancePath+"/sender",schemaPath:"#/properties/sender/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.recipient !== undefined){ -if(typeof data.recipient !== "string"){ -const err19 = {instancePath:instancePath+"/recipient",schemaPath:"#/properties/recipient/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err20 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data.delivery !== undefined){ -if(typeof data.delivery !== "string"){ -const err21 = {instancePath:instancePath+"/delivery",schemaPath:"#/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.subject !== undefined){ -if(typeof data.subject !== "string"){ -const err22 = {instancePath:instancePath+"/subject",schemaPath:"#/properties/subject/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.excerpt !== undefined){ -if(typeof data.excerpt !== "string"){ -const err23 = {instancePath:instancePath+"/excerpt",schemaPath:"#/properties/excerpt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.body !== undefined){ -let data8 = data.body; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.reference_id === undefined){ -const err24 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data8.digest === undefined){ -const err25 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data8.size === undefined){ -const err26 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data8.media_type === undefined){ -const err27 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data8.source === undefined){ -const err28 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data8.text !== undefined){ -let data9 = data8.text; -if((data9 !== null) && (typeof data9 !== "string")){ -const err29 = {instancePath:instancePath+"/body/text",schemaPath:"#/properties/body/properties/text/type",keyword:"type",params:{type: schema109.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data8.binary !== undefined){ -let data10 = data8.binary; -if((typeof data10 !== "string") && (data10 !== null)){ -const err30 = {instancePath:instancePath+"/body/binary",schemaPath:"#/properties/body/properties/binary/type",keyword:"type",params:{type: schema109.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data8.reference_id !== undefined){ -if(typeof data8.reference_id !== "string"){ -const err31 = {instancePath:instancePath+"/body/reference_id",schemaPath:"#/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data8.digest !== undefined){ -if(typeof data8.digest !== "string"){ -const err32 = {instancePath:instancePath+"/body/digest",schemaPath:"#/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data8.size !== undefined){ -let data13 = data8.size; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err33 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err34 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -else { -const err35 = {instancePath:instancePath+"/body/size",schemaPath:"#/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data8.media_type !== undefined){ -if(typeof data8.media_type !== "string"){ -const err36 = {instancePath:instancePath+"/body/media_type",schemaPath:"#/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data8.source !== undefined){ -if(typeof data8.source !== "string"){ -const err37 = {instancePath:instancePath+"/body/source",schemaPath:"#/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -} -else { -const err38 = {instancePath:instancePath+"/body",schemaPath:"#/properties/body/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data.evidence_handle !== undefined){ -if(typeof data.evidence_handle !== "string"){ -const err39 = {instancePath:instancePath+"/evidence_handle",schemaPath:"#/properties/evidence_handle/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err40 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data.available_at !== undefined){ -if(typeof data.available_at !== "string"){ -const err41 = {instancePath:instancePath+"/available_at",schemaPath:"#/properties/available_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data.created_at !== undefined){ -if(typeof data.created_at !== "string"){ -const err42 = {instancePath:instancePath+"/created_at",schemaPath:"#/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data.delivered_at !== undefined){ -if(typeof data.delivered_at !== "string"){ -const err43 = {instancePath:instancePath+"/delivered_at",schemaPath:"#/properties/delivered_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data.delivered_turn_id !== undefined){ -if(typeof data.delivered_turn_id !== "string"){ -const err44 = {instancePath:instancePath+"/delivered_turn_id",schemaPath:"#/properties/delivered_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.done_at !== undefined){ -if(typeof data.done_at !== "string"){ -const err45 = {instancePath:instancePath+"/done_at",schemaPath:"#/properties/done_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -else { -const err46 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -validate108.errors = vErrors; -return errors === 0; -} - -export const MailboxPage = validate109; -const schema110 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"sender":{"type":"string"},"recipient":{"type":"string"},"kind":{"type":"string"},"delivery":{"type":"string"},"subject":{"type":"string"},"excerpt":{"type":"string"},"body":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"evidence_handle":{"type":"string"},"status":{"type":"string"},"available_at":{"type":"string"},"created_at":{"type":"string"},"delivered_at":{"type":"string"},"delivered_turn_id":{"type":"string"},"done_at":{"type":"string"}},"required":["id","revision","sender","recipient","kind","delivery","subject","excerpt","body","status","available_at","created_at","delivered_at","done_at"],"additionalProperties":true}},"next_cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","status","revision","offset"],"additionalProperties":true},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/MailboxPage","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxPage","required":["revision","items","has_more"],"additionalProperties":true}; - -function validate109(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.has_more === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.items !== undefined){ -let data1 = data.items; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err6 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema110.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.revision === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.sender === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "sender"},message:"must have required property '"+"sender"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.recipient === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "recipient"},message:"must have required property '"+"recipient"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.kind === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.delivery === undefined){ -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "delivery"},message:"must have required property '"+"delivery"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.subject === undefined){ -const err13 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "subject"},message:"must have required property '"+"subject"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.excerpt === undefined){ -const err14 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "excerpt"},message:"must have required property '"+"excerpt"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.body === undefined){ -const err15 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.status === undefined){ -const err16 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.available_at === undefined){ -const err17 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "available_at"},message:"must have required property '"+"available_at"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data2.created_at === undefined){ -const err18 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data2.delivered_at === undefined){ -const err19 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "delivered_at"},message:"must have required property '"+"delivered_at"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data2.done_at === undefined){ -const err20 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "done_at"},message:"must have required property '"+"done_at"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.revision !== undefined){ -let data4 = data2.revision; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -else { -const err24 = {instancePath:instancePath+"/items/" + i0+"/revision",schemaPath:"#/properties/items/items/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.sender !== undefined){ -if(typeof data2.sender !== "string"){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/sender",schemaPath:"#/properties/items/items/properties/sender/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.recipient !== undefined){ -if(typeof data2.recipient !== "string"){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/recipient",schemaPath:"#/properties/items/items/properties/recipient/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/kind",schemaPath:"#/properties/items/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data2.delivery !== undefined){ -if(typeof data2.delivery !== "string"){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/delivery",schemaPath:"#/properties/items/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data2.subject !== undefined){ -if(typeof data2.subject !== "string"){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/subject",schemaPath:"#/properties/items/items/properties/subject/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data2.excerpt !== undefined){ -if(typeof data2.excerpt !== "string"){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/excerpt",schemaPath:"#/properties/items/items/properties/excerpt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data2.body !== undefined){ -let data11 = data2.body; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.reference_id === undefined){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data11.digest === undefined){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data11.size === undefined){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data11.media_type === undefined){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data11.source === undefined){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data11.text !== undefined){ -let data12 = data11.text; -if((data12 !== null) && (typeof data12 !== "string")){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/properties/body/properties/text/type",keyword:"type",params:{type: schema110.properties.items.items.properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data11.binary !== undefined){ -let data13 = data11.binary; -if((typeof data13 !== "string") && (data13 !== null)){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/properties/body/properties/binary/type",keyword:"type",params:{type: schema110.properties.items.items.properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data11.reference_id !== undefined){ -if(typeof data11.reference_id !== "string"){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data11.digest !== undefined){ -if(typeof data11.digest !== "string"){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data11.size !== undefined){ -let data16 = data11.size; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data11.media_type !== undefined){ -if(typeof data11.media_type !== "string"){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data11.source !== undefined){ -if(typeof data11.source !== "string"){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -else { -const err45 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/properties/body/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data2.evidence_handle !== undefined){ -if(typeof data2.evidence_handle !== "string"){ -const err46 = {instancePath:instancePath+"/items/" + i0+"/evidence_handle",schemaPath:"#/properties/items/items/properties/evidence_handle/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/status",schemaPath:"#/properties/items/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data2.available_at !== undefined){ -if(typeof data2.available_at !== "string"){ -const err48 = {instancePath:instancePath+"/items/" + i0+"/available_at",schemaPath:"#/properties/items/items/properties/available_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data2.created_at !== undefined){ -if(typeof data2.created_at !== "string"){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/created_at",schemaPath:"#/properties/items/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -if(data2.delivered_at !== undefined){ -if(typeof data2.delivered_at !== "string"){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/delivered_at",schemaPath:"#/properties/items/items/properties/delivered_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data2.delivered_turn_id !== undefined){ -if(typeof data2.delivered_turn_id !== "string"){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/delivered_turn_id",schemaPath:"#/properties/items/items/properties/delivered_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data2.done_at !== undefined){ -if(typeof data2.done_at !== "string"){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/done_at",schemaPath:"#/properties/items/items/properties/done_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -} -else { -const err53 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -} -} -if(data.next_cursor !== undefined){ -let data26 = data.next_cursor; -if((data26 !== null) && (!(data26 && typeof data26 == "object" && !Array.isArray(data26)))){ -const err54 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema110.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data26 && typeof data26 == "object" && !Array.isArray(data26)){ -if(data26.root_id === undefined){ -const err55 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data26.agent_id === undefined){ -const err56 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data26.status === undefined){ -const err57 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data26.revision === undefined){ -const err58 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data26.offset === undefined){ -const err59 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -if(data26.root_id !== undefined){ -if(typeof data26.root_id !== "string"){ -const err60 = {instancePath:instancePath+"/next_cursor/root_id",schemaPath:"#/properties/next_cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data26.agent_id !== undefined){ -if(typeof data26.agent_id !== "string"){ -const err61 = {instancePath:instancePath+"/next_cursor/agent_id",schemaPath:"#/properties/next_cursor/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data26.status !== undefined){ -if(typeof data26.status !== "string"){ -const err62 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data26.revision !== undefined){ -let data30 = data26.revision; -if(typeof data30 === "string"){ -if(!pattern0.test(data30)){ -const err63 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(!(formats0.validate(data30))){ -const err64 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -else { -const err65 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data26.offset !== undefined){ -let data31 = data26.offset; -if(typeof data31 === "string"){ -if(!pattern0.test(data31)){ -const err66 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(!(formats0.validate(data31))){ -const err67 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -else { -const err68 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err69 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -} -else { -const err70 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -validate109.errors = vErrors; -return errors === 0; -} - -export const MailboxPageParams = validate110; -const schema111 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"status":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","status","revision","offset"],"additionalProperties":true},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/MailboxPageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxPageParams","required":["root_id","agent_id","limit","max_bytes"],"additionalProperties":true}; - -function validate110(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxPageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.max_bytes === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err5 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err6 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data3 = data.cursor; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema111.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.root_id === undefined){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data3.agent_id === undefined){ -const err9 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data3.status === undefined){ -const err10 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data3.revision === undefined){ -const err11 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data3.offset === undefined){ -const err12 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data3.root_id !== undefined){ -if(typeof data3.root_id !== "string"){ -const err13 = {instancePath:instancePath+"/cursor/root_id",schemaPath:"#/properties/cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data3.agent_id !== undefined){ -if(typeof data3.agent_id !== "string"){ -const err14 = {instancePath:instancePath+"/cursor/agent_id",schemaPath:"#/properties/cursor/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data3.status !== undefined){ -if(typeof data3.status !== "string"){ -const err15 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data3.revision !== undefined){ -let data7 = data3.revision; -if(typeof data7 === "string"){ -if(!pattern0.test(data7)){ -const err16 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(formats0.validate(data7))){ -const err17 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -else { -const err18 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data3.offset !== undefined){ -let data8 = data3.offset; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err19 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err20 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -else { -const err21 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data9 = data.limit; -if(!((typeof data9 == "number") && (!(data9 % 1) && !isNaN(data9)))){ -const err22 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data10 = data.max_bytes; -if(!((typeof data10 == "number") && (!(data10 % 1) && !isNaN(data10)))){ -const err23 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -validate110.errors = vErrors; -return errors === 0; -} - -export const MailboxReadParams = validate111; -const schema112 = {"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/MailboxReadParams","$schema":"http://json-schema.org/draft-07/schema#","title":"MailboxReadParams","required":["root_id","agent_id","id"],"additionalProperties":true}; - -function validate111(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/MailboxReadParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.agent_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err4 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err5 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate111.errors = vErrors; -return errors === 0; -} - -export const ModelParams = validate112; -const schema113 = {"type":"object","properties":{"effort":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"persist_default":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ModelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ModelParams","required":["model","persist_default"],"additionalProperties":true}; - -function validate112(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ModelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.persist_default === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "persist_default"},message:"must have required property '"+"persist_default"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err2 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err3 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.persist_default !== undefined){ -if(typeof data.persist_default !== "boolean"){ -const err5 = {instancePath:instancePath+"/persist_default",schemaPath:"#/properties/persist_default/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate112.errors = vErrors; -return errors === 0; -} - -export const ModelResult = validate113; -const schema114 = {"type":"object","properties":{"reload_pending":{"type":"boolean"},"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ModelResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ModelResult","required":["model","provider"],"additionalProperties":true}; - -function validate113(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ModelResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.reload_pending !== undefined){ -if(typeof data.reload_pending !== "boolean"){ -const err2 = {instancePath:instancePath+"/reload_pending",schemaPath:"#/properties/reload_pending/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err3 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate113.errors = vErrors; -return errors === 0; -} - -export const PathParams = validate114; -const schema115 = {"type":"object","properties":{"path":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PathParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PathParams","required":["path"],"additionalProperties":true}; - -function validate114(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PathParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err1 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate114.errors = vErrors; -return errors === 0; -} - -export const PathResult = validate115; -const schema116 = {"type":"object","properties":{"path":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PathResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PathResult","required":["path"],"additionalProperties":true}; - -function validate115(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PathResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.path === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "path"},message:"must have required property '"+"path"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.path !== undefined){ -if(typeof data.path !== "string"){ -const err1 = {instancePath:instancePath+"/path",schemaPath:"#/properties/path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate115.errors = vErrors; -return errors === 0; -} - -export const PermissionConfigureParams = validate116; -const schema117 = {"type":"object","properties":{"external_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/PermissionConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionConfigureParams","required":["external_permissions"],"additionalProperties":true}; - -function validate116(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.external_permissions === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "external_permissions"},message:"must have required property '"+"external_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.external_permissions !== undefined){ -if(typeof data.external_permissions !== "boolean"){ -const err1 = {instancePath:instancePath+"/external_permissions",schemaPath:"#/properties/external_permissions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate116.errors = vErrors; -return errors === 0; -} - -export const PermissionDecision = validate117; -const schema118 = {"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"permission_id":{"type":"string"},"allow":{"type":"boolean"},"reason":{"type":"string"},"remember":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PermissionDecision","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecision","required":["command_id","root_id","permission_id","allow"],"additionalProperties":true}; - -function validate117(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecision" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.permission_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permission_id"},message:"must have required property '"+"permission_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.allow === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "allow"},message:"must have required property '"+"allow"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.command_id !== undefined){ -if(typeof data.command_id !== "string"){ -const err4 = {instancePath:instancePath+"/command_id",schemaPath:"#/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.permission_id !== undefined){ -if(typeof data.permission_id !== "string"){ -const err6 = {instancePath:instancePath+"/permission_id",schemaPath:"#/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.allow !== undefined){ -if(typeof data.allow !== "boolean"){ -const err7 = {instancePath:instancePath+"/allow",schemaPath:"#/properties/allow/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err8 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.remember !== undefined){ -if(typeof data.remember !== "string"){ -const err9 = {instancePath:instancePath+"/remember",schemaPath:"#/properties/remember/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -validate117.errors = vErrors; -return errors === 0; -} - -export const PermissionDecisionParams = validate118; -const schema119 = {"type":"object","properties":{"decision":{"type":"object","properties":{"command_id":{"type":"string"},"root_id":{"type":"string"},"permission_id":{"type":"string"},"allow":{"type":"boolean"},"reason":{"type":"string"},"remember":{"type":"string"}},"required":["command_id","root_id","permission_id","allow"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/PermissionDecisionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecisionParams","required":["decision"],"additionalProperties":true}; - -function validate118(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecisionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.decision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "decision"},message:"must have required property '"+"decision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.decision !== undefined){ -let data0 = data.decision; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.command_id === undefined){ -const err1 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "command_id"},message:"must have required property '"+"command_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.root_id === undefined){ -const err2 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.permission_id === undefined){ -const err3 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "permission_id"},message:"must have required property '"+"permission_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.allow === undefined){ -const err4 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/required",keyword:"required",params:{missingProperty: "allow"},message:"must have required property '"+"allow"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.command_id !== undefined){ -if(typeof data0.command_id !== "string"){ -const err5 = {instancePath:instancePath+"/decision/command_id",schemaPath:"#/properties/decision/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.root_id !== undefined){ -if(typeof data0.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/decision/root_id",schemaPath:"#/properties/decision/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.permission_id !== undefined){ -if(typeof data0.permission_id !== "string"){ -const err7 = {instancePath:instancePath+"/decision/permission_id",schemaPath:"#/properties/decision/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.allow !== undefined){ -if(typeof data0.allow !== "boolean"){ -const err8 = {instancePath:instancePath+"/decision/allow",schemaPath:"#/properties/decision/properties/allow/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.reason !== undefined){ -if(typeof data0.reason !== "string"){ -const err9 = {instancePath:instancePath+"/decision/reason",schemaPath:"#/properties/decision/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.remember !== undefined){ -if(typeof data0.remember !== "string"){ -const err10 = {instancePath:instancePath+"/decision/remember",schemaPath:"#/properties/decision/properties/remember/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/decision",schemaPath:"#/properties/decision/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate118.errors = vErrors; -return errors === 0; -} - -export const PermissionDecisionResult = validate119; -const schema120 = {"type":"object","properties":{"operation_id":{"type":"string"},"lease_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PermissionDecisionResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionDecisionResult","required":["operation_id","lease_id"],"additionalProperties":true}; - -function validate119(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionDecisionResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.lease_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "lease_id"},message:"must have required property '"+"lease_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err2 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.lease_id !== undefined){ -if(typeof data.lease_id !== "string"){ -const err3 = {instancePath:instancePath+"/lease_id",schemaPath:"#/properties/lease_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate119.errors = vErrors; -return errors === 0; -} - -export const PermissionRulesResult = validate120; -const schema121 = {"type":"object","properties":{"rules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"operation":{"type":"string"},"rule":{"type":"string"},"principal_id":{"type":"string"},"created_at":{"type":"string"}},"required":["id","root_id","operation","rule","principal_id","created_at"],"additionalProperties":true}},"global":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/PermissionRulesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PermissionRulesResult","required":["rules","global"],"additionalProperties":true}; - -function validate120(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PermissionRulesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.rules === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rules"},message:"must have required property '"+"rules"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.global === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "global"},message:"must have required property '"+"global"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.rules !== undefined){ -let data0 = data.rules; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/rules",schemaPath:"#/properties/rules/type",keyword:"type",params:{type: schema121.properties.rules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err3 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.root_id === undefined){ -const err4 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.operation === undefined){ -const err5 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.rule === undefined){ -const err6 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.principal_id === undefined){ -const err7 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "principal_id"},message:"must have required property '"+"principal_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.created_at === undefined){ -const err8 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err9 = {instancePath:instancePath+"/rules/" + i0+"/id",schemaPath:"#/properties/rules/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err10 = {instancePath:instancePath+"/rules/" + i0+"/root_id",schemaPath:"#/properties/rules/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.operation !== undefined){ -if(typeof data1.operation !== "string"){ -const err11 = {instancePath:instancePath+"/rules/" + i0+"/operation",schemaPath:"#/properties/rules/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.rule !== undefined){ -if(typeof data1.rule !== "string"){ -const err12 = {instancePath:instancePath+"/rules/" + i0+"/rule",schemaPath:"#/properties/rules/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.principal_id !== undefined){ -if(typeof data1.principal_id !== "string"){ -const err13 = {instancePath:instancePath+"/rules/" + i0+"/principal_id",schemaPath:"#/properties/rules/items/properties/principal_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.created_at !== undefined){ -if(typeof data1.created_at !== "string"){ -const err14 = {instancePath:instancePath+"/rules/" + i0+"/created_at",schemaPath:"#/properties/rules/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/rules/" + i0,schemaPath:"#/properties/rules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data.global !== undefined){ -let data8 = data.global; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err16 = {instancePath:instancePath+"/global",schemaPath:"#/properties/global/type",keyword:"type",params:{type: schema121.properties.global.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err17 = {instancePath:instancePath+"/global/" + i1,schemaPath:"#/properties/global/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -} -else { -const err18 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -validate120.errors = vErrors; -return errors === 0; -} - -export const PingResult = validate121; -const schema122 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"build_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/PingResult","$schema":"http://json-schema.org/draft-07/schema#","title":"PingResult","required":["generation","build_id"],"additionalProperties":true}; - -function validate121(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/PingResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.build_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "build_id"},message:"must have required property '"+"build_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.build_id !== undefined){ -if(typeof data.build_id !== "string"){ -const err5 = {instancePath:instancePath+"/build_id",schemaPath:"#/properties/build_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate121.errors = vErrors; -return errors === 0; -} - -export const ProviderCatalogParams = validate122; -const schema123 = {"type":"object","properties":{"refresh":{"type":"boolean"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderCatalogParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCatalogParams","additionalProperties":true}; - -function validate122(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCatalogParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.refresh !== undefined){ -if(typeof data.refresh !== "boolean"){ -const err0 = {instancePath:instancePath+"/refresh",schemaPath:"#/properties/refresh/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err1 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate122.errors = vErrors; -return errors === 0; -} - -export const ProviderCatalogsResult = validate123; -const schema124 = {"type":"object","properties":{"models":{"type":"object","additionalProperties":{"type":"object","properties":{"name":{"type":"string"},"id":{"type":"string"},"providers":{"type":["null","array"],"items":{"type":"string"}},"context":{"type":"integer"},"vision":{"type":"boolean"}},"required":["providers"],"additionalProperties":true}},"providers":{"type":"object","additionalProperties":{"type":"object","properties":{"base_url":{"type":"string"},"available":{"type":["null","boolean"]}},"required":["base_url"],"additionalProperties":true}},"catalogs":{"type":"object","additionalProperties":{"type":"object","properties":{"fetched_at":{"type":"string"},"base_url":{"type":"string"},"models":{"type":["null","array"],"items":{"type":"object","properties":{"pricing":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"completion":{"type":"string"},"input_cache_read":{"type":"string"}},"required":["prompt","completion"],"additionalProperties":true},"pricing_known":{"type":"boolean"},"cache_read_price_known":{"type":"boolean"},"id":{"type":"string"},"context_length":{"type":"integer"},"max_completion_tokens":{"type":"integer"},"reasoning_efforts":{"type":["null","array"],"items":{"type":"string"}},"in_price":{"type":"number"},"out_price":{"type":"number"},"cache_read_price":{"type":"number"},"input_modalities":{"type":["null","array"],"items":{"type":"string"}}},"required":["id"],"additionalProperties":true}}},"required":["fetched_at","base_url","models"],"additionalProperties":true}},"errors":{"type":"object","additionalProperties":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ProviderCatalogsResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCatalogsResult","required":["models","providers","catalogs"],"additionalProperties":true}; - -function validate123(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCatalogsResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.models === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.providers === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.catalogs === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "catalogs"},message:"must have required property '"+"catalogs"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.models !== undefined){ -let data0 = data.models; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -for(const key0 in data0){ -let data1 = data0[key0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.providers === undefined){ -const err3 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/models/additionalProperties/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.name !== undefined){ -if(typeof data1.name !== "string"){ -const err4 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/name",schemaPath:"#/properties/models/additionalProperties/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err5 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/id",schemaPath:"#/properties/models/additionalProperties/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.providers !== undefined){ -let data4 = data1.providers; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err6 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/providers",schemaPath:"#/properties/models/additionalProperties/properties/providers/type",keyword:"type",params:{type: schema124.properties.models.additionalProperties.properties.providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data4[i0] !== "string"){ -const err7 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/providers/" + i0,schemaPath:"#/properties/models/additionalProperties/properties/providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -} -if(data1.context !== undefined){ -let data6 = data1.context; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err8 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/context",schemaPath:"#/properties/models/additionalProperties/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.vision !== undefined){ -if(typeof data1.vision !== "boolean"){ -const err9 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/vision",schemaPath:"#/properties/models/additionalProperties/properties/vision/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/models/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/models/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.providers !== undefined){ -let data8 = data.providers; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -for(const key1 in data8){ -let data9 = data8[key1]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.base_url === undefined){ -const err12 = {instancePath:instancePath+"/providers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/providers/additionalProperties/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data9.base_url !== undefined){ -if(typeof data9.base_url !== "string"){ -const err13 = {instancePath:instancePath+"/providers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/base_url",schemaPath:"#/properties/providers/additionalProperties/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data9.available !== undefined){ -let data11 = data9.available; -if((data11 !== null) && (typeof data11 !== "boolean")){ -const err14 = {instancePath:instancePath+"/providers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1")+"/available",schemaPath:"#/properties/providers/additionalProperties/properties/available/type",keyword:"type",params:{type: schema124.properties.providers.additionalProperties.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/providers/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/providers/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath:instancePath+"/providers",schemaPath:"#/properties/providers/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.catalogs !== undefined){ -let data12 = data.catalogs; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -for(const key2 in data12){ -let data13 = data12[key2]; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.fetched_at === undefined){ -const err17 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "fetched_at"},message:"must have required property '"+"fetched_at"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data13.base_url === undefined){ -const err18 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data13.models === undefined){ -const err19 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data13.fetched_at !== undefined){ -if(typeof data13.fetched_at !== "string"){ -const err20 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/fetched_at",schemaPath:"#/properties/catalogs/additionalProperties/properties/fetched_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data13.base_url !== undefined){ -if(typeof data13.base_url !== "string"){ -const err21 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/base_url",schemaPath:"#/properties/catalogs/additionalProperties/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data13.models !== undefined){ -let data16 = data13.models; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err22 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data16)){ -const len1 = data16.length; -for(let i1=0; i1<len1; i1++){ -let data17 = data16[i1]; -if(data17 && typeof data17 == "object" && !Array.isArray(data17)){ -if(data17.id === undefined){ -const err23 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data17.pricing !== undefined){ -let data18 = data17.pricing; -if((data18 !== null) && (!(data18 && typeof data18 == "object" && !Array.isArray(data18)))){ -const err24 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.pricing.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data18 && typeof data18 == "object" && !Array.isArray(data18)){ -if(data18.prompt === undefined){ -const err25 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data18.completion === undefined){ -const err26 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "completion"},message:"must have required property '"+"completion"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data18.prompt !== undefined){ -if(typeof data18.prompt !== "string"){ -const err27 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/prompt",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data18.completion !== undefined){ -if(typeof data18.completion !== "string"){ -const err28 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/completion",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/completion/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data18.input_cache_read !== undefined){ -if(typeof data18.input_cache_read !== "string"){ -const err29 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing/input_cache_read",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing/properties/input_cache_read/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -} -if(data17.pricing_known !== undefined){ -if(typeof data17.pricing_known !== "boolean"){ -const err30 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/pricing_known",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/pricing_known/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data17.cache_read_price_known !== undefined){ -if(typeof data17.cache_read_price_known !== "boolean"){ -const err31 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/cache_read_price_known",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/cache_read_price_known/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data17.id !== undefined){ -if(typeof data17.id !== "string"){ -const err32 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/id",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data17.context_length !== undefined){ -let data25 = data17.context_length; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err33 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/context_length",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/context_length/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data17.max_completion_tokens !== undefined){ -let data26 = data17.max_completion_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err34 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/max_completion_tokens",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/max_completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data17.reasoning_efforts !== undefined){ -let data27 = data17.reasoning_efforts; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err35 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/reasoning_efforts",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/reasoning_efforts/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.reasoning_efforts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err36 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/reasoning_efforts/" + i2,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/reasoning_efforts/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -} -} -if(data17.in_price !== undefined){ -if(!(typeof data17.in_price == "number")){ -const err37 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/in_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/in_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data17.out_price !== undefined){ -if(!(typeof data17.out_price == "number")){ -const err38 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/out_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/out_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data17.cache_read_price !== undefined){ -if(!(typeof data17.cache_read_price == "number")){ -const err39 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/cache_read_price",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/cache_read_price/type",keyword:"type",params:{type: "number"},message:"must be number"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data17.input_modalities !== undefined){ -let data32 = data17.input_modalities; -if((data32 !== null) && (!(Array.isArray(data32)))){ -const err40 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/input_modalities",schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/input_modalities/type",keyword:"type",params:{type: schema124.properties.catalogs.additionalProperties.properties.models.items.properties.input_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(Array.isArray(data32)){ -const len3 = data32.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data32[i3] !== "string"){ -const err41 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1+"/input_modalities/" + i3,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/properties/input_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -} -} -else { -const err42 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/models/" + i1,schemaPath:"#/properties/catalogs/additionalProperties/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -} -} -else { -const err43 = {instancePath:instancePath+"/catalogs/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/catalogs/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -else { -const err44 = {instancePath:instancePath+"/catalogs",schemaPath:"#/properties/catalogs/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.errors !== undefined){ -let data34 = data.errors; -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -for(const key3 in data34){ -if(typeof data34[key3] !== "string"){ -const err45 = {instancePath:instancePath+"/errors/" + key3.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/errors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -} -else { -const err46 = {instancePath:instancePath+"/errors",schemaPath:"#/properties/errors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -} -else { -const err47 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -validate123.errors = vErrors; -return errors === 0; -} - -export const ProviderConfiguration = validate124; -const schema125 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"definition":{"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"api":{"type":"string"}},"required":["name","base_url","api"],"additionalProperties":true},"custom":{"type":"boolean"},"credential":{"type":"object","properties":{"mode":{"type":"string"},"configured":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"available":{"type":["null","boolean"]}},"required":["mode","configured"],"additionalProperties":true},"models":{"type":["null","array"],"items":{"type":"object","properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":true}},"removal_blockers":{"type":["null","array"],"items":{"type":"string"}},"discovery":{"type":["null","object"],"properties":{"status":{"type":"string"},"message":{"type":"string"},"model_count":{"type":"integer"}},"required":["status"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/ProviderConfiguration","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderConfiguration","required":["revision","provider","definition","custom","credential","models","removal_blockers"],"additionalProperties":true}; - -function validate124(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderConfiguration" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.definition === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.custom === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "custom"},message:"must have required property '"+"custom"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.credential === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "credential"},message:"must have required property '"+"credential"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.models === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.removal_blockers === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "removal_blockers"},message:"must have required property '"+"removal_blockers"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err7 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err8 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.definition !== undefined){ -let data2 = data.definition; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err9 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.base_url === undefined){ -const err10 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.api === undefined){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "api"},message:"must have required property '"+"api"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err12 = {instancePath:instancePath+"/definition/name",schemaPath:"#/properties/definition/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data2.base_url !== undefined){ -if(typeof data2.base_url !== "string"){ -const err13 = {instancePath:instancePath+"/definition/base_url",schemaPath:"#/properties/definition/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data2.api !== undefined){ -if(typeof data2.api !== "string"){ -const err14 = {instancePath:instancePath+"/definition/api",schemaPath:"#/properties/definition/properties/api/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -else { -const err15 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.custom !== undefined){ -if(typeof data.custom !== "boolean"){ -const err16 = {instancePath:instancePath+"/custom",schemaPath:"#/properties/custom/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.credential !== undefined){ -let data7 = data.credential; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.mode === undefined){ -const err17 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.configured === undefined){ -const err18 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.mode !== undefined){ -if(typeof data7.mode !== "string"){ -const err19 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data7.configured !== undefined){ -if(typeof data7.configured !== "boolean"){ -const err20 = {instancePath:instancePath+"/credential/configured",schemaPath:"#/properties/credential/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data7.environment_variable !== undefined){ -if(typeof data7.environment_variable !== "string"){ -const err21 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.credential_path !== undefined){ -if(typeof data7.credential_path !== "string"){ -const err22 = {instancePath:instancePath+"/credential/credential_path",schemaPath:"#/properties/credential/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.available !== undefined){ -let data12 = data7.available; -if((data12 !== null) && (typeof data12 !== "boolean")){ -const err23 = {instancePath:instancePath+"/credential/available",schemaPath:"#/properties/credential/properties/available/type",keyword:"type",params:{type: schema125.properties.credential.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.models !== undefined){ -let data13 = data.models; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err25 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: schema125.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(Array.isArray(data13)){ -const len0 = data13.length; -for(let i0=0; i0<len0; i0++){ -let data14 = data13[i0]; -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.alias === undefined){ -const err26 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data14.id === undefined){ -const err27 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data14.alias !== undefined){ -if(typeof data14.alias !== "string"){ -const err28 = {instancePath:instancePath+"/models/" + i0+"/alias",schemaPath:"#/properties/models/items/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data14.id !== undefined){ -if(typeof data14.id !== "string"){ -const err29 = {instancePath:instancePath+"/models/" + i0+"/id",schemaPath:"#/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data14.context !== undefined){ -let data17 = data14.context; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err30 = {instancePath:instancePath+"/models/" + i0+"/context",schemaPath:"#/properties/models/items/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data14.max_output !== undefined){ -let data18 = data14.max_output; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err31 = {instancePath:instancePath+"/models/" + i0+"/max_output",schemaPath:"#/properties/models/items/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -else { -const err32 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -} -if(data.removal_blockers !== undefined){ -let data19 = data.removal_blockers; -if((data19 !== null) && (!(Array.isArray(data19)))){ -const err33 = {instancePath:instancePath+"/removal_blockers",schemaPath:"#/properties/removal_blockers/type",keyword:"type",params:{type: schema125.properties.removal_blockers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(Array.isArray(data19)){ -const len1 = data19.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data19[i1] !== "string"){ -const err34 = {instancePath:instancePath+"/removal_blockers/" + i1,schemaPath:"#/properties/removal_blockers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -} -if(data.discovery !== undefined){ -let data21 = data.discovery; -if((data21 !== null) && (!(data21 && typeof data21 == "object" && !Array.isArray(data21)))){ -const err35 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/type",keyword:"type",params:{type: schema125.properties.discovery.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data21 && typeof data21 == "object" && !Array.isArray(data21)){ -if(data21.status === undefined){ -const err36 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data21.status !== undefined){ -if(typeof data21.status !== "string"){ -const err37 = {instancePath:instancePath+"/discovery/status",schemaPath:"#/properties/discovery/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data21.message !== undefined){ -if(typeof data21.message !== "string"){ -const err38 = {instancePath:instancePath+"/discovery/message",schemaPath:"#/properties/discovery/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data21.model_count !== undefined){ -let data24 = data21.model_count; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err39 = {instancePath:instancePath+"/discovery/model_count",schemaPath:"#/properties/discovery/properties/model_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -} -} -} -else { -const err40 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -validate124.errors = vErrors; -return errors === 0; -} - -export const ProviderCreateParams = validate125; -const schema126 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"definition":{"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"api":{"type":"string"}},"required":["name","base_url","api"],"additionalProperties":true},"credential":{"type":"object","properties":{"mode":{"type":"string"},"key":{"type":"string"},"environment_variable":{"type":"string"}},"required":["mode"],"additionalProperties":true},"manual_model":{"type":["null","object"],"properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":true},"allow_unverified":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderCreateParams","required":["revision","provider","definition","credential"],"additionalProperties":true}; - -function validate125(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.definition === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.credential === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "credential"},message:"must have required property '"+"credential"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err5 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.definition !== undefined){ -let data2 = data.definition; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err6 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2.base_url === undefined){ -const err7 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.api === undefined){ -const err8 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/required",keyword:"required",params:{missingProperty: "api"},message:"must have required property '"+"api"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err9 = {instancePath:instancePath+"/definition/name",schemaPath:"#/properties/definition/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data2.base_url !== undefined){ -if(typeof data2.base_url !== "string"){ -const err10 = {instancePath:instancePath+"/definition/base_url",schemaPath:"#/properties/definition/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data2.api !== undefined){ -if(typeof data2.api !== "string"){ -const err11 = {instancePath:instancePath+"/definition/api",schemaPath:"#/properties/definition/properties/api/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.credential !== undefined){ -let data6 = data.credential; -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.mode === undefined){ -const err13 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data6.mode !== undefined){ -if(typeof data6.mode !== "string"){ -const err14 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data6.key !== undefined){ -if(typeof data6.key !== "string"){ -const err15 = {instancePath:instancePath+"/credential/key",schemaPath:"#/properties/credential/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data6.environment_variable !== undefined){ -if(typeof data6.environment_variable !== "string"){ -const err16 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.manual_model !== undefined){ -let data10 = data.manual_model; -if((data10 !== null) && (!(data10 && typeof data10 == "object" && !Array.isArray(data10)))){ -const err18 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/type",keyword:"type",params:{type: schema126.properties.manual_model.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.alias === undefined){ -const err19 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data10.id === undefined){ -const err20 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data10.alias !== undefined){ -if(typeof data10.alias !== "string"){ -const err21 = {instancePath:instancePath+"/manual_model/alias",schemaPath:"#/properties/manual_model/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data10.id !== undefined){ -if(typeof data10.id !== "string"){ -const err22 = {instancePath:instancePath+"/manual_model/id",schemaPath:"#/properties/manual_model/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data10.context !== undefined){ -let data13 = data10.context; -if(!((typeof data13 == "number") && (!(data13 % 1) && !isNaN(data13)))){ -const err23 = {instancePath:instancePath+"/manual_model/context",schemaPath:"#/properties/manual_model/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data10.max_output !== undefined){ -let data14 = data10.max_output; -if(!((typeof data14 == "number") && (!(data14 % 1) && !isNaN(data14)))){ -const err24 = {instancePath:instancePath+"/manual_model/max_output",schemaPath:"#/properties/manual_model/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -} -if(data.allow_unverified !== undefined){ -if(typeof data.allow_unverified !== "boolean"){ -const err25 = {instancePath:instancePath+"/allow_unverified",schemaPath:"#/properties/allow_unverified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -else { -const err26 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -validate125.errors = vErrors; -return errors === 0; -} - -export const ProviderDisconnectParams = validate126; -const schema127 = {"type":"object","properties":{"provider":{"type":"string"},"revision":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderDisconnectParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderDisconnectParams","required":["provider","revision"],"additionalProperties":true}; - -function validate126(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderDisconnectParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err2 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate126.errors = vErrors; -return errors === 0; -} - -export const ProviderKeySetup = validate127; -const schema128 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"key":{"type":"string"},"environment":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderKeySetup","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderKeySetup","required":["revision","provider","environment"],"additionalProperties":true}; - -function validate127(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderKeySetup" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.environment === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "environment"},message:"must have required property '"+"environment"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err5 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.environment !== undefined){ -if(typeof data.environment !== "boolean"){ -const err6 = {instancePath:instancePath+"/environment",schemaPath:"#/properties/environment/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate127.errors = vErrors; -return errors === 0; -} - -export const ProviderList = validate128; -const schema129 = {"type":"object","properties":{"revision":{"type":"string"},"discovery_error":{"type":"string"},"default_provider":{"type":"string"},"providers":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"custom":{"type":"boolean"},"methods":{"type":["null","array"],"items":{"type":"string"}},"status":{"type":"object","properties":{"provider":{"type":"string"},"configured":{"type":"boolean"},"key_source":{"type":"string"},"available":{"type":["null","boolean"]},"disabled":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"auth_method":{"type":"string"},"auth_state":{"type":"string"},"account_id":{"type":"string"},"plan":{"type":"string"},"email":{"type":"string"},"team_name":{"type":"string"},"project_id":{"type":"string"},"project_name":{"type":"string"},"machine_key_name":{"type":"string"},"warnings":{"type":["null","array"],"items":{"type":"string"}}},"required":["provider","configured","key_source","warnings"],"additionalProperties":true},"recommended":{"type":"boolean"},"suggested_model":{"type":"string"},"category":{"type":"string"},"family":{"type":"string"},"key_url":{"type":"string"}},"required":["id","name","custom","methods","status"],"additionalProperties":true}},"selection":{"type":["null","object"],"properties":{"ready":{"type":"boolean"},"model":{"type":"string"},"provider":{"type":"string"},"reason":{"type":"string"}},"required":["ready","model","provider","reason"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/ProviderList","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderList","required":["revision","providers"],"additionalProperties":true}; - -function validate128(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.providers === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "providers"},message:"must have required property '"+"providers"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.discovery_error !== undefined){ -if(typeof data.discovery_error !== "string"){ -const err3 = {instancePath:instancePath+"/discovery_error",schemaPath:"#/properties/discovery_error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.default_provider !== undefined){ -if(typeof data.default_provider !== "string"){ -const err4 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.providers !== undefined){ -let data3 = data.providers; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err5 = {instancePath:instancePath+"/providers",schemaPath:"#/properties/providers/type",keyword:"type",params:{type: schema129.properties.providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.id === undefined){ -const err6 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data4.name === undefined){ -const err7 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4.custom === undefined){ -const err8 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "custom"},message:"must have required property '"+"custom"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.methods === undefined){ -const err9 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "methods"},message:"must have required property '"+"methods"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data4.status === undefined){ -const err10 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data4.id !== undefined){ -if(typeof data4.id !== "string"){ -const err11 = {instancePath:instancePath+"/providers/" + i0+"/id",schemaPath:"#/properties/providers/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data4.name !== undefined){ -if(typeof data4.name !== "string"){ -const err12 = {instancePath:instancePath+"/providers/" + i0+"/name",schemaPath:"#/properties/providers/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data4.custom !== undefined){ -if(typeof data4.custom !== "boolean"){ -const err13 = {instancePath:instancePath+"/providers/" + i0+"/custom",schemaPath:"#/properties/providers/items/properties/custom/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data4.methods !== undefined){ -let data8 = data4.methods; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err14 = {instancePath:instancePath+"/providers/" + i0+"/methods",schemaPath:"#/properties/providers/items/properties/methods/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.methods.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data8[i1] !== "string"){ -const err15 = {instancePath:instancePath+"/providers/" + i0+"/methods/" + i1,schemaPath:"#/properties/providers/items/properties/methods/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data4.status !== undefined){ -let data10 = data4.status; -if(data10 && typeof data10 == "object" && !Array.isArray(data10)){ -if(data10.provider === undefined){ -const err16 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data10.configured === undefined){ -const err17 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data10.key_source === undefined){ -const err18 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "key_source"},message:"must have required property '"+"key_source"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data10.warnings === undefined){ -const err19 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/required",keyword:"required",params:{missingProperty: "warnings"},message:"must have required property '"+"warnings"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data10.provider !== undefined){ -if(typeof data10.provider !== "string"){ -const err20 = {instancePath:instancePath+"/providers/" + i0+"/status/provider",schemaPath:"#/properties/providers/items/properties/status/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data10.configured !== undefined){ -if(typeof data10.configured !== "boolean"){ -const err21 = {instancePath:instancePath+"/providers/" + i0+"/status/configured",schemaPath:"#/properties/providers/items/properties/status/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data10.key_source !== undefined){ -if(typeof data10.key_source !== "string"){ -const err22 = {instancePath:instancePath+"/providers/" + i0+"/status/key_source",schemaPath:"#/properties/providers/items/properties/status/properties/key_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data10.available !== undefined){ -let data14 = data10.available; -if((data14 !== null) && (typeof data14 !== "boolean")){ -const err23 = {instancePath:instancePath+"/providers/" + i0+"/status/available",schemaPath:"#/properties/providers/items/properties/status/properties/available/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.status.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data10.disabled !== undefined){ -if(typeof data10.disabled !== "boolean"){ -const err24 = {instancePath:instancePath+"/providers/" + i0+"/status/disabled",schemaPath:"#/properties/providers/items/properties/status/properties/disabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data10.environment_variable !== undefined){ -if(typeof data10.environment_variable !== "string"){ -const err25 = {instancePath:instancePath+"/providers/" + i0+"/status/environment_variable",schemaPath:"#/properties/providers/items/properties/status/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data10.credential_path !== undefined){ -if(typeof data10.credential_path !== "string"){ -const err26 = {instancePath:instancePath+"/providers/" + i0+"/status/credential_path",schemaPath:"#/properties/providers/items/properties/status/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data10.auth_method !== undefined){ -if(typeof data10.auth_method !== "string"){ -const err27 = {instancePath:instancePath+"/providers/" + i0+"/status/auth_method",schemaPath:"#/properties/providers/items/properties/status/properties/auth_method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data10.auth_state !== undefined){ -if(typeof data10.auth_state !== "string"){ -const err28 = {instancePath:instancePath+"/providers/" + i0+"/status/auth_state",schemaPath:"#/properties/providers/items/properties/status/properties/auth_state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data10.account_id !== undefined){ -if(typeof data10.account_id !== "string"){ -const err29 = {instancePath:instancePath+"/providers/" + i0+"/status/account_id",schemaPath:"#/properties/providers/items/properties/status/properties/account_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data10.plan !== undefined){ -if(typeof data10.plan !== "string"){ -const err30 = {instancePath:instancePath+"/providers/" + i0+"/status/plan",schemaPath:"#/properties/providers/items/properties/status/properties/plan/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data10.email !== undefined){ -if(typeof data10.email !== "string"){ -const err31 = {instancePath:instancePath+"/providers/" + i0+"/status/email",schemaPath:"#/properties/providers/items/properties/status/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data10.team_name !== undefined){ -if(typeof data10.team_name !== "string"){ -const err32 = {instancePath:instancePath+"/providers/" + i0+"/status/team_name",schemaPath:"#/properties/providers/items/properties/status/properties/team_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data10.project_id !== undefined){ -if(typeof data10.project_id !== "string"){ -const err33 = {instancePath:instancePath+"/providers/" + i0+"/status/project_id",schemaPath:"#/properties/providers/items/properties/status/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data10.project_name !== undefined){ -if(typeof data10.project_name !== "string"){ -const err34 = {instancePath:instancePath+"/providers/" + i0+"/status/project_name",schemaPath:"#/properties/providers/items/properties/status/properties/project_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data10.machine_key_name !== undefined){ -if(typeof data10.machine_key_name !== "string"){ -const err35 = {instancePath:instancePath+"/providers/" + i0+"/status/machine_key_name",schemaPath:"#/properties/providers/items/properties/status/properties/machine_key_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data10.warnings !== undefined){ -let data27 = data10.warnings; -if((data27 !== null) && (!(Array.isArray(data27)))){ -const err36 = {instancePath:instancePath+"/providers/" + i0+"/status/warnings",schemaPath:"#/properties/providers/items/properties/status/properties/warnings/type",keyword:"type",params:{type: schema129.properties.providers.items.properties.status.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(Array.isArray(data27)){ -const len2 = data27.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data27[i2] !== "string"){ -const err37 = {instancePath:instancePath+"/providers/" + i0+"/status/warnings/" + i2,schemaPath:"#/properties/providers/items/properties/status/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -} -} -} -else { -const err38 = {instancePath:instancePath+"/providers/" + i0+"/status",schemaPath:"#/properties/providers/items/properties/status/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data4.recommended !== undefined){ -if(typeof data4.recommended !== "boolean"){ -const err39 = {instancePath:instancePath+"/providers/" + i0+"/recommended",schemaPath:"#/properties/providers/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data4.suggested_model !== undefined){ -if(typeof data4.suggested_model !== "string"){ -const err40 = {instancePath:instancePath+"/providers/" + i0+"/suggested_model",schemaPath:"#/properties/providers/items/properties/suggested_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data4.category !== undefined){ -if(typeof data4.category !== "string"){ -const err41 = {instancePath:instancePath+"/providers/" + i0+"/category",schemaPath:"#/properties/providers/items/properties/category/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data4.family !== undefined){ -if(typeof data4.family !== "string"){ -const err42 = {instancePath:instancePath+"/providers/" + i0+"/family",schemaPath:"#/properties/providers/items/properties/family/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data4.key_url !== undefined){ -if(typeof data4.key_url !== "string"){ -const err43 = {instancePath:instancePath+"/providers/" + i0+"/key_url",schemaPath:"#/properties/providers/items/properties/key_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -else { -const err44 = {instancePath:instancePath+"/providers/" + i0,schemaPath:"#/properties/providers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -} -} -if(data.selection !== undefined){ -let data34 = data.selection; -if((data34 !== null) && (!(data34 && typeof data34 == "object" && !Array.isArray(data34)))){ -const err45 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/type",keyword:"type",params:{type: schema129.properties.selection.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -if(data34.ready === undefined){ -const err46 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "ready"},message:"must have required property '"+"ready"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data34.model === undefined){ -const err47 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data34.provider === undefined){ -const err48 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data34.reason === undefined){ -const err49 = {instancePath:instancePath+"/selection",schemaPath:"#/properties/selection/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data34.ready !== undefined){ -if(typeof data34.ready !== "boolean"){ -const err50 = {instancePath:instancePath+"/selection/ready",schemaPath:"#/properties/selection/properties/ready/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data34.model !== undefined){ -if(typeof data34.model !== "string"){ -const err51 = {instancePath:instancePath+"/selection/model",schemaPath:"#/properties/selection/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data34.provider !== undefined){ -if(typeof data34.provider !== "string"){ -const err52 = {instancePath:instancePath+"/selection/provider",schemaPath:"#/properties/selection/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data34.reason !== undefined){ -if(typeof data34.reason !== "string"){ -const err53 = {instancePath:instancePath+"/selection/reason",schemaPath:"#/properties/selection/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -} -} -} -else { -const err54 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -validate128.errors = vErrors; -return errors === 0; -} - -export const ProviderListParams = validate129; -const schema130 = {"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderListParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderListParams","additionalProperties":true}; - -function validate129(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderListParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err0 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err1 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate129.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginBeginParams = validate130; -const schema131 = {"type":"object","properties":{"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginBeginParams","additionalProperties":true}; - -function validate130(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginBeginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err0 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -} -else { -const err1 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -validate130.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginCreateParams = validate131; -const schema132 = {"type":"object","properties":{"flow_id":{"type":"string"},"name":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginCreateParams","required":["flow_id","name"],"additionalProperties":true}; - -function validate131(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.name === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err2 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err3 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate131.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginList = validate132; -const schema133 = {"type":"object","properties":{"flows":{"type":["null","array"],"items":{"type":"object","properties":{"flow_id":{"type":"string"},"provider":{"type":"string"},"state":{"type":"string"},"verification_url":{"type":"string"},"user_code":{"type":"string"},"email":{"type":"string"},"teams":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":true}},"projects":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":true}},"team_id":{"type":"string"},"project_id":{"type":"string"},"expires_at":{"type":"string"},"error":{"type":"string"}},"required":["flow_id","state","teams","projects","expires_at"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/ProviderLoginList","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginList","required":["flows"],"additionalProperties":true}; - -function validate132(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginList" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flows === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flows"},message:"must have required property '"+"flows"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.flows !== undefined){ -let data0 = data.flows; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/flows",schemaPath:"#/properties/flows/type",keyword:"type",params:{type: schema133.properties.flows.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.flow_id === undefined){ -const err2 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1.state === undefined){ -const err3 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.teams === undefined){ -const err4 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "teams"},message:"must have required property '"+"teams"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.projects === undefined){ -const err5 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "projects"},message:"must have required property '"+"projects"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.expires_at === undefined){ -const err6 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.flow_id !== undefined){ -if(typeof data1.flow_id !== "string"){ -const err7 = {instancePath:instancePath+"/flows/" + i0+"/flow_id",schemaPath:"#/properties/flows/items/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.provider !== undefined){ -if(typeof data1.provider !== "string"){ -const err8 = {instancePath:instancePath+"/flows/" + i0+"/provider",schemaPath:"#/properties/flows/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data1.state !== undefined){ -if(typeof data1.state !== "string"){ -const err9 = {instancePath:instancePath+"/flows/" + i0+"/state",schemaPath:"#/properties/flows/items/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data1.verification_url !== undefined){ -if(typeof data1.verification_url !== "string"){ -const err10 = {instancePath:instancePath+"/flows/" + i0+"/verification_url",schemaPath:"#/properties/flows/items/properties/verification_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.user_code !== undefined){ -if(typeof data1.user_code !== "string"){ -const err11 = {instancePath:instancePath+"/flows/" + i0+"/user_code",schemaPath:"#/properties/flows/items/properties/user_code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data1.email !== undefined){ -if(typeof data1.email !== "string"){ -const err12 = {instancePath:instancePath+"/flows/" + i0+"/email",schemaPath:"#/properties/flows/items/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.teams !== undefined){ -let data8 = data1.teams; -if((data8 !== null) && (!(Array.isArray(data8)))){ -const err13 = {instancePath:instancePath+"/flows/" + i0+"/teams",schemaPath:"#/properties/flows/items/properties/teams/type",keyword:"type",params:{type: schema133.properties.flows.items.properties.teams.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(Array.isArray(data8)){ -const len1 = data8.length; -for(let i1=0; i1<len1; i1++){ -let data9 = data8[i1]; -if(data9 && typeof data9 == "object" && !Array.isArray(data9)){ -if(data9.id === undefined){ -const err14 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data9.name === undefined){ -const err15 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data9.id !== undefined){ -if(typeof data9.id !== "string"){ -const err16 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1+"/id",schemaPath:"#/properties/flows/items/properties/teams/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data9.name !== undefined){ -if(typeof data9.name !== "string"){ -const err17 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1+"/name",schemaPath:"#/properties/flows/items/properties/teams/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -else { -const err18 = {instancePath:instancePath+"/flows/" + i0+"/teams/" + i1,schemaPath:"#/properties/flows/items/properties/teams/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data1.projects !== undefined){ -let data12 = data1.projects; -if((data12 !== null) && (!(Array.isArray(data12)))){ -const err19 = {instancePath:instancePath+"/flows/" + i0+"/projects",schemaPath:"#/properties/flows/items/properties/projects/type",keyword:"type",params:{type: schema133.properties.flows.items.properties.projects.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(Array.isArray(data12)){ -const len2 = data12.length; -for(let i2=0; i2<len2; i2++){ -let data13 = data12[i2]; -if(data13 && typeof data13 == "object" && !Array.isArray(data13)){ -if(data13.id === undefined){ -const err20 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data13.name === undefined){ -const err21 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data13.id !== undefined){ -if(typeof data13.id !== "string"){ -const err22 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2+"/id",schemaPath:"#/properties/flows/items/properties/projects/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data13.name !== undefined){ -if(typeof data13.name !== "string"){ -const err23 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2+"/name",schemaPath:"#/properties/flows/items/properties/projects/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -} -else { -const err24 = {instancePath:instancePath+"/flows/" + i0+"/projects/" + i2,schemaPath:"#/properties/flows/items/properties/projects/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -} -if(data1.team_id !== undefined){ -if(typeof data1.team_id !== "string"){ -const err25 = {instancePath:instancePath+"/flows/" + i0+"/team_id",schemaPath:"#/properties/flows/items/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data1.project_id !== undefined){ -if(typeof data1.project_id !== "string"){ -const err26 = {instancePath:instancePath+"/flows/" + i0+"/project_id",schemaPath:"#/properties/flows/items/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data1.expires_at !== undefined){ -if(typeof data1.expires_at !== "string"){ -const err27 = {instancePath:instancePath+"/flows/" + i0+"/expires_at",schemaPath:"#/properties/flows/items/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data1.error !== undefined){ -if(typeof data1.error !== "string"){ -const err28 = {instancePath:instancePath+"/flows/" + i0+"/error",schemaPath:"#/properties/flows/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -else { -const err29 = {instancePath:instancePath+"/flows/" + i0,schemaPath:"#/properties/flows/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -} -} -} -else { -const err30 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -validate132.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginParams = validate133; -const schema134 = {"type":"object","properties":{"flow_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginParams","required":["flow_id"],"additionalProperties":true}; - -function validate133(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err1 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate133.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginProjectParams = validate134; -const schema135 = {"type":"object","properties":{"flow_id":{"type":"string"},"project_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginProjectParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginProjectParams","required":["flow_id","project_id"],"additionalProperties":true}; - -function validate134(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginProjectParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.project_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "project_id"},message:"must have required property '"+"project_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err2 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err3 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate134.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginStatus = validate135; -const schema136 = {"type":"object","properties":{"flow_id":{"type":"string"},"provider":{"type":"string"},"state":{"type":"string"},"verification_url":{"type":"string"},"user_code":{"type":"string"},"email":{"type":"string"},"teams":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":true}},"projects":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":true}},"team_id":{"type":"string"},"project_id":{"type":"string"},"expires_at":{"type":"string"},"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginStatus","required":["flow_id","state","teams","projects","expires_at"],"additionalProperties":true}; - -function validate135(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.state === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.teams === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "teams"},message:"must have required property '"+"teams"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.projects === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "projects"},message:"must have required property '"+"projects"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.expires_at === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err5 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err6 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.state !== undefined){ -if(typeof data.state !== "string"){ -const err7 = {instancePath:instancePath+"/state",schemaPath:"#/properties/state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.verification_url !== undefined){ -if(typeof data.verification_url !== "string"){ -const err8 = {instancePath:instancePath+"/verification_url",schemaPath:"#/properties/verification_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.user_code !== undefined){ -if(typeof data.user_code !== "string"){ -const err9 = {instancePath:instancePath+"/user_code",schemaPath:"#/properties/user_code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.email !== undefined){ -if(typeof data.email !== "string"){ -const err10 = {instancePath:instancePath+"/email",schemaPath:"#/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.teams !== undefined){ -let data6 = data.teams; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err11 = {instancePath:instancePath+"/teams",schemaPath:"#/properties/teams/type",keyword:"type",params:{type: schema136.properties.teams.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(Array.isArray(data6)){ -const len0 = data6.length; -for(let i0=0; i0<len0; i0++){ -let data7 = data6[i0]; -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.id === undefined){ -const err12 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7.name === undefined){ -const err13 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.id !== undefined){ -if(typeof data7.id !== "string"){ -const err14 = {instancePath:instancePath+"/teams/" + i0+"/id",schemaPath:"#/properties/teams/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data7.name !== undefined){ -if(typeof data7.name !== "string"){ -const err15 = {instancePath:instancePath+"/teams/" + i0+"/name",schemaPath:"#/properties/teams/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath:instancePath+"/teams/" + i0,schemaPath:"#/properties/teams/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -if(data.projects !== undefined){ -let data10 = data.projects; -if((data10 !== null) && (!(Array.isArray(data10)))){ -const err17 = {instancePath:instancePath+"/projects",schemaPath:"#/properties/projects/type",keyword:"type",params:{type: schema136.properties.projects.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(Array.isArray(data10)){ -const len1 = data10.length; -for(let i1=0; i1<len1; i1++){ -let data11 = data10[i1]; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.id === undefined){ -const err18 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data11.name === undefined){ -const err19 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data11.id !== undefined){ -if(typeof data11.id !== "string"){ -const err20 = {instancePath:instancePath+"/projects/" + i1+"/id",schemaPath:"#/properties/projects/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data11.name !== undefined){ -if(typeof data11.name !== "string"){ -const err21 = {instancePath:instancePath+"/projects/" + i1+"/name",schemaPath:"#/properties/projects/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -else { -const err22 = {instancePath:instancePath+"/projects/" + i1,schemaPath:"#/properties/projects/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -} -if(data.team_id !== undefined){ -if(typeof data.team_id !== "string"){ -const err23 = {instancePath:instancePath+"/team_id",schemaPath:"#/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err24 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.expires_at !== undefined){ -if(typeof data.expires_at !== "string"){ -const err25 = {instancePath:instancePath+"/expires_at",schemaPath:"#/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err26 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -} -else { -const err27 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -validate135.errors = vErrors; -return errors === 0; -} - -export const ProviderLoginTeamParams = validate136; -const schema137 = {"type":"object","properties":{"flow_id":{"type":"string"},"team_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderLoginTeamParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderLoginTeamParams","required":["flow_id","team_id"],"additionalProperties":true}; - -function validate136(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderLoginTeamParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.flow_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "flow_id"},message:"must have required property '"+"flow_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.team_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "team_id"},message:"must have required property '"+"team_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.flow_id !== undefined){ -if(typeof data.flow_id !== "string"){ -const err2 = {instancePath:instancePath+"/flow_id",schemaPath:"#/properties/flow_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.team_id !== undefined){ -if(typeof data.team_id !== "string"){ -const err3 = {instancePath:instancePath+"/team_id",schemaPath:"#/properties/team_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate136.errors = vErrors; -return errors === 0; -} - -export const ProviderNameParams = validate137; -const schema138 = {"type":"object","properties":{"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderNameParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderNameParams","required":["provider"],"additionalProperties":true}; - -function validate137(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderNameParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err1 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate137.errors = vErrors; -return errors === 0; -} - -export const ProviderRemoveParams = validate138; -const schema139 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderRemoveParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderRemoveParams","required":["revision","provider"],"additionalProperties":true}; - -function validate138(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderRemoveParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err3 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate138.errors = vErrors; -return errors === 0; -} - -export const ProviderRemoveResult = validate139; -const schema140 = {"type":"object","properties":{"revision":{"type":"string"},"warning":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderRemoveResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderRemoveResult","required":["revision"],"additionalProperties":true}; - -function validate139(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderRemoveResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err1 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.warning !== undefined){ -if(typeof data.warning !== "string"){ -const err2 = {instancePath:instancePath+"/warning",schemaPath:"#/properties/warning/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate139.errors = vErrors; -return errors === 0; -} - -export const ProviderStatus = validate140; -const schema141 = {"type":"object","properties":{"provider":{"type":"string"},"configured":{"type":"boolean"},"key_source":{"type":"string"},"available":{"type":["null","boolean"]},"disabled":{"type":"boolean"},"environment_variable":{"type":"string"},"credential_path":{"type":"string"},"auth_method":{"type":"string"},"auth_state":{"type":"string"},"account_id":{"type":"string"},"plan":{"type":"string"},"email":{"type":"string"},"team_name":{"type":"string"},"project_id":{"type":"string"},"project_name":{"type":"string"},"machine_key_name":{"type":"string"},"warnings":{"type":["null","array"],"items":{"type":"string"}}},"$id":"https://whip.dev/protocol/v6/ProviderStatus","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderStatus","required":["provider","configured","key_source","warnings"],"additionalProperties":true}; - -function validate140(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderStatus" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.provider === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.configured === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "configured"},message:"must have required property '"+"configured"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.key_source === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "key_source"},message:"must have required property '"+"key_source"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.warnings === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "warnings"},message:"must have required property '"+"warnings"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err4 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.configured !== undefined){ -if(typeof data.configured !== "boolean"){ -const err5 = {instancePath:instancePath+"/configured",schemaPath:"#/properties/configured/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.key_source !== undefined){ -if(typeof data.key_source !== "string"){ -const err6 = {instancePath:instancePath+"/key_source",schemaPath:"#/properties/key_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.available !== undefined){ -let data3 = data.available; -if((data3 !== null) && (typeof data3 !== "boolean")){ -const err7 = {instancePath:instancePath+"/available",schemaPath:"#/properties/available/type",keyword:"type",params:{type: schema141.properties.available.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.disabled !== undefined){ -if(typeof data.disabled !== "boolean"){ -const err8 = {instancePath:instancePath+"/disabled",schemaPath:"#/properties/disabled/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.environment_variable !== undefined){ -if(typeof data.environment_variable !== "string"){ -const err9 = {instancePath:instancePath+"/environment_variable",schemaPath:"#/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.credential_path !== undefined){ -if(typeof data.credential_path !== "string"){ -const err10 = {instancePath:instancePath+"/credential_path",schemaPath:"#/properties/credential_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.auth_method !== undefined){ -if(typeof data.auth_method !== "string"){ -const err11 = {instancePath:instancePath+"/auth_method",schemaPath:"#/properties/auth_method/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.auth_state !== undefined){ -if(typeof data.auth_state !== "string"){ -const err12 = {instancePath:instancePath+"/auth_state",schemaPath:"#/properties/auth_state/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.account_id !== undefined){ -if(typeof data.account_id !== "string"){ -const err13 = {instancePath:instancePath+"/account_id",schemaPath:"#/properties/account_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.plan !== undefined){ -if(typeof data.plan !== "string"){ -const err14 = {instancePath:instancePath+"/plan",schemaPath:"#/properties/plan/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.email !== undefined){ -if(typeof data.email !== "string"){ -const err15 = {instancePath:instancePath+"/email",schemaPath:"#/properties/email/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.team_name !== undefined){ -if(typeof data.team_name !== "string"){ -const err16 = {instancePath:instancePath+"/team_name",schemaPath:"#/properties/team_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.project_id !== undefined){ -if(typeof data.project_id !== "string"){ -const err17 = {instancePath:instancePath+"/project_id",schemaPath:"#/properties/project_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.project_name !== undefined){ -if(typeof data.project_name !== "string"){ -const err18 = {instancePath:instancePath+"/project_name",schemaPath:"#/properties/project_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.machine_key_name !== undefined){ -if(typeof data.machine_key_name !== "string"){ -const err19 = {instancePath:instancePath+"/machine_key_name",schemaPath:"#/properties/machine_key_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.warnings !== undefined){ -let data16 = data.warnings; -if((data16 !== null) && (!(Array.isArray(data16)))){ -const err20 = {instancePath:instancePath+"/warnings",schemaPath:"#/properties/warnings/type",keyword:"type",params:{type: schema141.properties.warnings.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(Array.isArray(data16)){ -const len0 = data16.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data16[i0] !== "string"){ -const err21 = {instancePath:instancePath+"/warnings/" + i0,schemaPath:"#/properties/warnings/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -} -else { -const err22 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -validate140.errors = vErrors; -return errors === 0; -} - -export const ProviderUpdateParams = validate141; -const schema142 = {"type":"object","properties":{"revision":{"type":"string"},"provider":{"type":"string"},"name":{"type":["null","string"]},"base_url":{"type":["null","string"]},"credential":{"type":["null","object"],"properties":{"mode":{"type":"string"},"key":{"type":"string"},"environment_variable":{"type":"string"}},"required":["mode"],"additionalProperties":true},"manual_model":{"type":["null","object"],"properties":{"alias":{"type":"string"},"id":{"type":"string"},"context":{"type":"integer"},"max_output":{"type":"integer"}},"required":["alias","id"],"additionalProperties":true},"allow_unverified":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ProviderUpdateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderUpdateParams","required":["revision","provider"],"additionalProperties":true}; - -function validate141(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderUpdateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.provider === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err2 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err3 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.name !== undefined){ -let data2 = data.name; -if((data2 !== null) && (typeof data2 !== "string")){ -const err4 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: schema142.properties.name.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.base_url !== undefined){ -let data3 = data.base_url; -if((data3 !== null) && (typeof data3 !== "string")){ -const err5 = {instancePath:instancePath+"/base_url",schemaPath:"#/properties/base_url/type",keyword:"type",params:{type: schema142.properties.base_url.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.credential !== undefined){ -let data4 = data.credential; -if((data4 !== null) && (!(data4 && typeof data4 == "object" && !Array.isArray(data4)))){ -const err6 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/type",keyword:"type",params:{type: schema142.properties.credential.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.mode === undefined){ -const err7 = {instancePath:instancePath+"/credential",schemaPath:"#/properties/credential/required",keyword:"required",params:{missingProperty: "mode"},message:"must have required property '"+"mode"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data4.mode !== undefined){ -if(typeof data4.mode !== "string"){ -const err8 = {instancePath:instancePath+"/credential/mode",schemaPath:"#/properties/credential/properties/mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data4.key !== undefined){ -if(typeof data4.key !== "string"){ -const err9 = {instancePath:instancePath+"/credential/key",schemaPath:"#/properties/credential/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data4.environment_variable !== undefined){ -if(typeof data4.environment_variable !== "string"){ -const err10 = {instancePath:instancePath+"/credential/environment_variable",schemaPath:"#/properties/credential/properties/environment_variable/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data.manual_model !== undefined){ -let data8 = data.manual_model; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err11 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/type",keyword:"type",params:{type: schema142.properties.manual_model.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.alias === undefined){ -const err12 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "alias"},message:"must have required property '"+"alias"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data8.id === undefined){ -const err13 = {instancePath:instancePath+"/manual_model",schemaPath:"#/properties/manual_model/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data8.alias !== undefined){ -if(typeof data8.alias !== "string"){ -const err14 = {instancePath:instancePath+"/manual_model/alias",schemaPath:"#/properties/manual_model/properties/alias/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data8.id !== undefined){ -if(typeof data8.id !== "string"){ -const err15 = {instancePath:instancePath+"/manual_model/id",schemaPath:"#/properties/manual_model/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data8.context !== undefined){ -let data11 = data8.context; -if(!((typeof data11 == "number") && (!(data11 % 1) && !isNaN(data11)))){ -const err16 = {instancePath:instancePath+"/manual_model/context",schemaPath:"#/properties/manual_model/properties/context/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data8.max_output !== undefined){ -let data12 = data8.max_output; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err17 = {instancePath:instancePath+"/manual_model/max_output",schemaPath:"#/properties/manual_model/properties/max_output/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.allow_unverified !== undefined){ -if(typeof data.allow_unverified !== "boolean"){ -const err18 = {instancePath:instancePath+"/allow_unverified",schemaPath:"#/properties/allow_unverified/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -else { -const err19 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -validate141.errors = vErrors; -return errors === 0; -} - -export const ProviderValidateParams = validate142; -const schema143 = {"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string"},"key":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ProviderValidateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderValidateParams","required":["name","base_url","key"],"additionalProperties":true}; - -function validate142(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderValidateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.name === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.base_url === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "base_url"},message:"must have required property '"+"base_url"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.key === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err3 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.base_url !== undefined){ -if(typeof data.base_url !== "string"){ -const err4 = {instancePath:instancePath+"/base_url",schemaPath:"#/properties/base_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.key !== undefined){ -if(typeof data.key !== "string"){ -const err5 = {instancePath:instancePath+"/key",schemaPath:"#/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate142.errors = vErrors; -return errors === 0; -} - -export const ProviderValidateResult = validate143; -const schema144 = {"type":"object","properties":{"models":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"context_length":{"type":"integer"},"max_completion_tokens":{"type":"integer"},"reasoning_efforts":{"type":["null","array"],"items":{"type":"string"}},"pricing":{"type":["null","object"],"properties":{"prompt":{"type":"string"},"completion":{"type":"string"},"input_cache_read":{"type":"string"}},"required":["prompt","completion"],"additionalProperties":true},"input_modalities":{"type":["null","array"],"items":{"type":"string"}},"output_modalities":{"type":["null","array"],"items":{"type":"string"}},"supports_tools":{"type":["null","boolean"]},"type":{"type":"string"}},"required":["id"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/ProviderValidateResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ProviderValidateResult","required":["models"],"additionalProperties":true}; - -function validate143(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ProviderValidateResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.models === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "models"},message:"must have required property '"+"models"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.models !== undefined){ -let data0 = data.models; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/models",schemaPath:"#/properties/models/type",keyword:"type",params:{type: schema144.properties.models.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.id === undefined){ -const err2 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1.id !== undefined){ -if(typeof data1.id !== "string"){ -const err3 = {instancePath:instancePath+"/models/" + i0+"/id",schemaPath:"#/properties/models/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data1.context_length !== undefined){ -let data3 = data1.context_length; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err4 = {instancePath:instancePath+"/models/" + i0+"/context_length",schemaPath:"#/properties/models/items/properties/context_length/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.max_completion_tokens !== undefined){ -let data4 = data1.max_completion_tokens; -if(!((typeof data4 == "number") && (!(data4 % 1) && !isNaN(data4)))){ -const err5 = {instancePath:instancePath+"/models/" + i0+"/max_completion_tokens",schemaPath:"#/properties/models/items/properties/max_completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.reasoning_efforts !== undefined){ -let data5 = data1.reasoning_efforts; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err6 = {instancePath:instancePath+"/models/" + i0+"/reasoning_efforts",schemaPath:"#/properties/models/items/properties/reasoning_efforts/type",keyword:"type",params:{type: schema144.properties.models.items.properties.reasoning_efforts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data5)){ -const len1 = data5.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data5[i1] !== "string"){ -const err7 = {instancePath:instancePath+"/models/" + i0+"/reasoning_efforts/" + i1,schemaPath:"#/properties/models/items/properties/reasoning_efforts/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -} -if(data1.pricing !== undefined){ -let data7 = data1.pricing; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err8 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/type",keyword:"type",params:{type: schema144.properties.models.items.properties.pricing.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.prompt === undefined){ -const err9 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data7.completion === undefined){ -const err10 = {instancePath:instancePath+"/models/" + i0+"/pricing",schemaPath:"#/properties/models/items/properties/pricing/required",keyword:"required",params:{missingProperty: "completion"},message:"must have required property '"+"completion"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7.prompt !== undefined){ -if(typeof data7.prompt !== "string"){ -const err11 = {instancePath:instancePath+"/models/" + i0+"/pricing/prompt",schemaPath:"#/properties/models/items/properties/pricing/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data7.completion !== undefined){ -if(typeof data7.completion !== "string"){ -const err12 = {instancePath:instancePath+"/models/" + i0+"/pricing/completion",schemaPath:"#/properties/models/items/properties/pricing/properties/completion/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data7.input_cache_read !== undefined){ -if(typeof data7.input_cache_read !== "string"){ -const err13 = {instancePath:instancePath+"/models/" + i0+"/pricing/input_cache_read",schemaPath:"#/properties/models/items/properties/pricing/properties/input_cache_read/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -} -if(data1.input_modalities !== undefined){ -let data11 = data1.input_modalities; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err14 = {instancePath:instancePath+"/models/" + i0+"/input_modalities",schemaPath:"#/properties/models/items/properties/input_modalities/type",keyword:"type",params:{type: schema144.properties.models.items.properties.input_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(Array.isArray(data11)){ -const len2 = data11.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data11[i2] !== "string"){ -const err15 = {instancePath:instancePath+"/models/" + i0+"/input_modalities/" + i2,schemaPath:"#/properties/models/items/properties/input_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -} -if(data1.output_modalities !== undefined){ -let data13 = data1.output_modalities; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err16 = {instancePath:instancePath+"/models/" + i0+"/output_modalities",schemaPath:"#/properties/models/items/properties/output_modalities/type",keyword:"type",params:{type: schema144.properties.models.items.properties.output_modalities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data13)){ -const len3 = data13.length; -for(let i3=0; i3<len3; i3++){ -if(typeof data13[i3] !== "string"){ -const err17 = {instancePath:instancePath+"/models/" + i0+"/output_modalities/" + i3,schemaPath:"#/properties/models/items/properties/output_modalities/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data1.supports_tools !== undefined){ -let data15 = data1.supports_tools; -if((data15 !== null) && (typeof data15 !== "boolean")){ -const err18 = {instancePath:instancePath+"/models/" + i0+"/supports_tools",schemaPath:"#/properties/models/items/properties/supports_tools/type",keyword:"type",params:{type: schema144.properties.models.items.properties.supports_tools.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data1.type !== undefined){ -if(typeof data1.type !== "string"){ -const err19 = {instancePath:instancePath+"/models/" + i0+"/type",schemaPath:"#/properties/models/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath:instancePath+"/models/" + i0,schemaPath:"#/properties/models/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -} -} -else { -const err21 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -validate143.errors = vErrors; -return errors === 0; -} - -export const QueryParams = validate144; -const schema145 = {"type":"object","properties":{"root_id":{"type":"string"},"operation":{"type":"string"},"payload":true},"$id":"https://whip.dev/protocol/v6/QueryParams","$schema":"http://json-schema.org/draft-07/schema#","title":"QueryParams","required":["operation"],"additionalProperties":true}; - -function validate144(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QueryParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.operation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.operation !== undefined){ -if(typeof data.operation !== "string"){ -const err2 = {instancePath:instancePath+"/operation",schemaPath:"#/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate144.errors = vErrors; -return errors === 0; -} - -export const QueryResult = validate145; -const schema146 = {"type":"object","properties":{"result":true,"content":{"type":["null","object"],"properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/QueryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"QueryResult","additionalProperties":true}; - -function validate145(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QueryResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.content !== undefined){ -let data0 = data.content; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err0 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: schema146.properties.content.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err1 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.digest === undefined){ -const err2 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.size === undefined){ -const err3 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err4 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err5 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err6 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err7 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -else { -const err8 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err9 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err10 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err11 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate145.errors = vErrors; -return errors === 0; -} - -export const QuestionAnswerParams = validate146; -const schema147 = {"type":"object","properties":{"id":{"type":"string"},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/QuestionAnswerParams","$schema":"http://json-schema.org/draft-07/schema#","title":"QuestionAnswerParams","required":["id","answer","dismissed"],"additionalProperties":true}; - -function validate146(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/QuestionAnswerParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.answer === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "answer"},message:"must have required property '"+"answer"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.dismissed === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "dismissed"},message:"must have required property '"+"dismissed"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.answer !== undefined){ -let data1 = data.answer; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err4 = {instancePath:instancePath+"/answer",schemaPath:"#/properties/answer/type",keyword:"type",params:{type: schema147.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err5 = {instancePath:instancePath+"/answer/" + i0,schemaPath:"#/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -} -if(data.dismissed !== undefined){ -if(typeof data.dismissed !== "boolean"){ -const err6 = {instancePath:instancePath+"/dismissed",schemaPath:"#/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.answers !== undefined){ -let data4 = data.answers; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err7 = {instancePath:instancePath+"/answers",schemaPath:"#/properties/answers/type",keyword:"type",params:{type: schema147.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data4)){ -const len1 = data4.length; -for(let i1=0; i1<len1; i1++){ -let data5 = data4[i1]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.answer !== undefined){ -let data6 = data5.answer; -if((data6 !== null) && (!(Array.isArray(data6)))){ -const err8 = {instancePath:instancePath+"/answers/" + i1+"/answer",schemaPath:"#/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema147.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(Array.isArray(data6)){ -const len2 = data6.length; -for(let i2=0; i2<len2; i2++){ -if(typeof data6[i2] !== "string"){ -const err9 = {instancePath:instancePath+"/answers/" + i1+"/answer/" + i2,schemaPath:"#/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -} -if(data5.dismissed !== undefined){ -if(typeof data5.dismissed !== "boolean"){ -const err10 = {instancePath:instancePath+"/answers/" + i1+"/dismissed",schemaPath:"#/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/answers/" + i1,schemaPath:"#/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate146.errors = vErrors; -return errors === 0; -} - -export const RPCError = validate147; -const schema148 = {"type":"object","properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":true},"code":{"type":"integer"},"message":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RPCError","$schema":"http://json-schema.org/draft-07/schema#","title":"RPCError","required":["code","message"],"additionalProperties":true}; - -function validate147(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RPCError" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.code === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.message === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.data !== undefined){ -let data0 = data.data; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema148.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.kind === undefined){ -const err3 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err4 = {instancePath:instancePath+"/data/kind",schemaPath:"#/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -if(data.code !== undefined){ -let data2 = data.code; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.message !== undefined){ -if(typeof data.message !== "string"){ -const err6 = {instancePath:instancePath+"/message",schemaPath:"#/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate147.errors = vErrors; -return errors === 0; -} - -export const ReplayParams = validate148; -const schema149 = {"type":"object","properties":{"root_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ReplayParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ReplayParams","required":["root_id","cursor"],"additionalProperties":true}; - -function validate148(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ReplayParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err2 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.limit !== undefined){ -let data2 = data.limit; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err6 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate148.errors = vErrors; -return errors === 0; -} - -export const ReplayResult = validate149; -const schema150 = {"type":"object","properties":{"events":{"type":["null","array"],"items":{"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["root_id","seq","kind"],"additionalProperties":true}},"latest":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expired":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ReplayResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ReplayResult","required":["events","latest"],"additionalProperties":true}; - -function validate149(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ReplayResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.events === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "events"},message:"must have required property '"+"events"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.latest === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "latest"},message:"must have required property '"+"latest"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.events !== undefined){ -let data0 = data.events; -if((data0 !== null) && (!(Array.isArray(data0)))){ -const err2 = {instancePath:instancePath+"/events",schemaPath:"#/properties/events/type",keyword:"type",params:{type: schema150.properties.events.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(Array.isArray(data0)){ -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err3 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.seq === undefined){ -const err4 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.kind === undefined){ -const err5 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.subscription_id !== undefined){ -if(typeof data1.subscription_id !== "string"){ -const err6 = {instancePath:instancePath+"/events/" + i0+"/subscription_id",schemaPath:"#/properties/events/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err7 = {instancePath:instancePath+"/events/" + i0+"/root_id",schemaPath:"#/properties/events/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data1.seq !== undefined){ -let data4 = data1.seq; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err8 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err9 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/events/" + i0+"/seq",schemaPath:"#/properties/events/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data1.kind !== undefined){ -if(typeof data1.kind !== "string"){ -const err11 = {instancePath:instancePath+"/events/" + i0+"/kind",schemaPath:"#/properties/events/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath:instancePath+"/events/" + i0,schemaPath:"#/properties/events/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -if(data.latest !== undefined){ -let data6 = data.latest; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err13 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err14 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -else { -const err15 = {instancePath:instancePath+"/latest",schemaPath:"#/properties/latest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.expired !== undefined){ -if(typeof data.expired !== "boolean"){ -const err16 = {instancePath:instancePath+"/expired",schemaPath:"#/properties/expired/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -else { -const err17 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -validate149.errors = vErrors; -return errors === 0; -} - -export const Resolved = validate150; -const schema151 = {"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"dark":{"type":"boolean"},"colors":{"type":"object","properties":{"background":{"type":"string"},"foreground":{"type":"string"},"muted":{"type":"string"},"faint":{"type":"string"},"primary":{"type":"string"},"on_primary":{"type":"string"},"accent":{"type":"string"},"success":{"type":"string"},"warning":{"type":"string"},"error":{"type":"string"},"info":{"type":"string"},"link":{"type":"string"},"emphasis":{"type":"string"},"border":{"type":"string"},"border_focus":{"type":"string"},"diff_add":{"type":"string"},"diff_del":{"type":"string"},"panel":{"type":"string"},"element":{"type":"string"},"hover":{"type":"string"}},"required":["background","foreground","muted","faint","primary","on_primary","accent","success","warning","error","info","link","emphasis","border","border_focus","diff_add","diff_del","panel","element","hover"],"additionalProperties":true},"syntax":{"type":"object","properties":{"keyword":{"type":"string"},"string":{"type":"string"},"number":{"type":"string"},"comment":{"type":"string"},"function":{"type":"string"},"type":{"type":"string"},"operator":{"type":"string"},"punctuation":{"type":"string"}},"required":["keyword","string","number","comment","function","type","operator","punctuation"],"additionalProperties":true},"markdown":{"type":"object","properties":{"heading":{"type":"string"},"strong":{"type":"string"},"code":{"type":"string"},"quote":{"type":"string"}},"required":["heading","strong","code","quote"],"additionalProperties":true},"code":{"type":"object","properties":{"foreground":{"type":"string"},"background":{"type":"string"},"tokens":{"type":"object","additionalProperties":{"type":"object","properties":{"color":{"type":"string"},"background":{"type":"string"},"bold":{"type":"boolean"},"italic":{"type":"boolean"},"underline":{"type":"boolean"}},"required":["color","background","bold","italic","underline"],"additionalProperties":true}}},"required":["foreground","background","tokens"],"additionalProperties":true},"web":{"type":["null","object"],"properties":{"navigation":{"type":"string"},"quiet_border":{"type":"string"},"code_background":{"type":"string"},"inline_code_background":{"type":"string"}},"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/Resolved","$schema":"http://json-schema.org/draft-07/schema#","title":"Resolved","required":["id","name","dark","colors","syntax","markdown","code"],"additionalProperties":true}; - -function validate150(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/Resolved" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.name === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.dark === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "dark"},message:"must have required property '"+"dark"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.colors === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "colors"},message:"must have required property '"+"colors"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.syntax === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "syntax"},message:"must have required property '"+"syntax"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.markdown === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "markdown"},message:"must have required property '"+"markdown"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.code === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err7 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err8 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.dark !== undefined){ -if(typeof data.dark !== "boolean"){ -const err9 = {instancePath:instancePath+"/dark",schemaPath:"#/properties/dark/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.colors !== undefined){ -let data3 = data.colors; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.background === undefined){ -const err10 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data3.foreground === undefined){ -const err11 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "foreground"},message:"must have required property '"+"foreground"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data3.muted === undefined){ -const err12 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "muted"},message:"must have required property '"+"muted"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data3.faint === undefined){ -const err13 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "faint"},message:"must have required property '"+"faint"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data3.primary === undefined){ -const err14 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "primary"},message:"must have required property '"+"primary"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data3.on_primary === undefined){ -const err15 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "on_primary"},message:"must have required property '"+"on_primary"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data3.accent === undefined){ -const err16 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "accent"},message:"must have required property '"+"accent"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data3.success === undefined){ -const err17 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "success"},message:"must have required property '"+"success"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data3.warning === undefined){ -const err18 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "warning"},message:"must have required property '"+"warning"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data3.error === undefined){ -const err19 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "error"},message:"must have required property '"+"error"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data3.info === undefined){ -const err20 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "info"},message:"must have required property '"+"info"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data3.link === undefined){ -const err21 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "link"},message:"must have required property '"+"link"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data3.emphasis === undefined){ -const err22 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "emphasis"},message:"must have required property '"+"emphasis"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data3.border === undefined){ -const err23 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "border"},message:"must have required property '"+"border"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data3.border_focus === undefined){ -const err24 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "border_focus"},message:"must have required property '"+"border_focus"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data3.diff_add === undefined){ -const err25 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "diff_add"},message:"must have required property '"+"diff_add"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data3.diff_del === undefined){ -const err26 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "diff_del"},message:"must have required property '"+"diff_del"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data3.panel === undefined){ -const err27 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "panel"},message:"must have required property '"+"panel"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data3.element === undefined){ -const err28 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "element"},message:"must have required property '"+"element"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data3.hover === undefined){ -const err29 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/required",keyword:"required",params:{missingProperty: "hover"},message:"must have required property '"+"hover"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data3.background !== undefined){ -if(typeof data3.background !== "string"){ -const err30 = {instancePath:instancePath+"/colors/background",schemaPath:"#/properties/colors/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data3.foreground !== undefined){ -if(typeof data3.foreground !== "string"){ -const err31 = {instancePath:instancePath+"/colors/foreground",schemaPath:"#/properties/colors/properties/foreground/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data3.muted !== undefined){ -if(typeof data3.muted !== "string"){ -const err32 = {instancePath:instancePath+"/colors/muted",schemaPath:"#/properties/colors/properties/muted/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data3.faint !== undefined){ -if(typeof data3.faint !== "string"){ -const err33 = {instancePath:instancePath+"/colors/faint",schemaPath:"#/properties/colors/properties/faint/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data3.primary !== undefined){ -if(typeof data3.primary !== "string"){ -const err34 = {instancePath:instancePath+"/colors/primary",schemaPath:"#/properties/colors/properties/primary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data3.on_primary !== undefined){ -if(typeof data3.on_primary !== "string"){ -const err35 = {instancePath:instancePath+"/colors/on_primary",schemaPath:"#/properties/colors/properties/on_primary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data3.accent !== undefined){ -if(typeof data3.accent !== "string"){ -const err36 = {instancePath:instancePath+"/colors/accent",schemaPath:"#/properties/colors/properties/accent/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data3.success !== undefined){ -if(typeof data3.success !== "string"){ -const err37 = {instancePath:instancePath+"/colors/success",schemaPath:"#/properties/colors/properties/success/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data3.warning !== undefined){ -if(typeof data3.warning !== "string"){ -const err38 = {instancePath:instancePath+"/colors/warning",schemaPath:"#/properties/colors/properties/warning/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data3.error !== undefined){ -if(typeof data3.error !== "string"){ -const err39 = {instancePath:instancePath+"/colors/error",schemaPath:"#/properties/colors/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data3.info !== undefined){ -if(typeof data3.info !== "string"){ -const err40 = {instancePath:instancePath+"/colors/info",schemaPath:"#/properties/colors/properties/info/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data3.link !== undefined){ -if(typeof data3.link !== "string"){ -const err41 = {instancePath:instancePath+"/colors/link",schemaPath:"#/properties/colors/properties/link/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data3.emphasis !== undefined){ -if(typeof data3.emphasis !== "string"){ -const err42 = {instancePath:instancePath+"/colors/emphasis",schemaPath:"#/properties/colors/properties/emphasis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data3.border !== undefined){ -if(typeof data3.border !== "string"){ -const err43 = {instancePath:instancePath+"/colors/border",schemaPath:"#/properties/colors/properties/border/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data3.border_focus !== undefined){ -if(typeof data3.border_focus !== "string"){ -const err44 = {instancePath:instancePath+"/colors/border_focus",schemaPath:"#/properties/colors/properties/border_focus/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data3.diff_add !== undefined){ -if(typeof data3.diff_add !== "string"){ -const err45 = {instancePath:instancePath+"/colors/diff_add",schemaPath:"#/properties/colors/properties/diff_add/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data3.diff_del !== undefined){ -if(typeof data3.diff_del !== "string"){ -const err46 = {instancePath:instancePath+"/colors/diff_del",schemaPath:"#/properties/colors/properties/diff_del/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data3.panel !== undefined){ -if(typeof data3.panel !== "string"){ -const err47 = {instancePath:instancePath+"/colors/panel",schemaPath:"#/properties/colors/properties/panel/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -if(data3.element !== undefined){ -if(typeof data3.element !== "string"){ -const err48 = {instancePath:instancePath+"/colors/element",schemaPath:"#/properties/colors/properties/element/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -if(data3.hover !== undefined){ -if(typeof data3.hover !== "string"){ -const err49 = {instancePath:instancePath+"/colors/hover",schemaPath:"#/properties/colors/properties/hover/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -} -else { -const err50 = {instancePath:instancePath+"/colors",schemaPath:"#/properties/colors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -} -if(data.syntax !== undefined){ -let data24 = data.syntax; -if(data24 && typeof data24 == "object" && !Array.isArray(data24)){ -if(data24.keyword === undefined){ -const err51 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "keyword"},message:"must have required property '"+"keyword"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data24.string === undefined){ -const err52 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "string"},message:"must have required property '"+"string"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data24.number === undefined){ -const err53 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data24.comment === undefined){ -const err54 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "comment"},message:"must have required property '"+"comment"+"'"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -if(data24.function === undefined){ -const err55 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(data24.type === undefined){ -const err56 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data24.operator === undefined){ -const err57 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "operator"},message:"must have required property '"+"operator"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data24.punctuation === undefined){ -const err58 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/required",keyword:"required",params:{missingProperty: "punctuation"},message:"must have required property '"+"punctuation"+"'"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -if(data24.keyword !== undefined){ -if(typeof data24.keyword !== "string"){ -const err59 = {instancePath:instancePath+"/syntax/keyword",schemaPath:"#/properties/syntax/properties/keyword/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data24.string !== undefined){ -if(typeof data24.string !== "string"){ -const err60 = {instancePath:instancePath+"/syntax/string",schemaPath:"#/properties/syntax/properties/string/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data24.number !== undefined){ -if(typeof data24.number !== "string"){ -const err61 = {instancePath:instancePath+"/syntax/number",schemaPath:"#/properties/syntax/properties/number/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data24.comment !== undefined){ -if(typeof data24.comment !== "string"){ -const err62 = {instancePath:instancePath+"/syntax/comment",schemaPath:"#/properties/syntax/properties/comment/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data24.function !== undefined){ -if(typeof data24.function !== "string"){ -const err63 = {instancePath:instancePath+"/syntax/function",schemaPath:"#/properties/syntax/properties/function/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data24.type !== undefined){ -if(typeof data24.type !== "string"){ -const err64 = {instancePath:instancePath+"/syntax/type",schemaPath:"#/properties/syntax/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data24.operator !== undefined){ -if(typeof data24.operator !== "string"){ -const err65 = {instancePath:instancePath+"/syntax/operator",schemaPath:"#/properties/syntax/properties/operator/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data24.punctuation !== undefined){ -if(typeof data24.punctuation !== "string"){ -const err66 = {instancePath:instancePath+"/syntax/punctuation",schemaPath:"#/properties/syntax/properties/punctuation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -} -else { -const err67 = {instancePath:instancePath+"/syntax",schemaPath:"#/properties/syntax/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data.markdown !== undefined){ -let data33 = data.markdown; -if(data33 && typeof data33 == "object" && !Array.isArray(data33)){ -if(data33.heading === undefined){ -const err68 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "heading"},message:"must have required property '"+"heading"+"'"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -if(data33.strong === undefined){ -const err69 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "strong"},message:"must have required property '"+"strong"+"'"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -if(data33.code === undefined){ -const err70 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -if(data33.quote === undefined){ -const err71 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/required",keyword:"required",params:{missingProperty: "quote"},message:"must have required property '"+"quote"+"'"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -if(data33.heading !== undefined){ -if(typeof data33.heading !== "string"){ -const err72 = {instancePath:instancePath+"/markdown/heading",schemaPath:"#/properties/markdown/properties/heading/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data33.strong !== undefined){ -if(typeof data33.strong !== "string"){ -const err73 = {instancePath:instancePath+"/markdown/strong",schemaPath:"#/properties/markdown/properties/strong/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data33.code !== undefined){ -if(typeof data33.code !== "string"){ -const err74 = {instancePath:instancePath+"/markdown/code",schemaPath:"#/properties/markdown/properties/code/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data33.quote !== undefined){ -if(typeof data33.quote !== "string"){ -const err75 = {instancePath:instancePath+"/markdown/quote",schemaPath:"#/properties/markdown/properties/quote/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -} -else { -const err76 = {instancePath:instancePath+"/markdown",schemaPath:"#/properties/markdown/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.code !== undefined){ -let data38 = data.code; -if(data38 && typeof data38 == "object" && !Array.isArray(data38)){ -if(data38.foreground === undefined){ -const err77 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "foreground"},message:"must have required property '"+"foreground"+"'"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data38.background === undefined){ -const err78 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data38.tokens === undefined){ -const err79 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data38.foreground !== undefined){ -if(typeof data38.foreground !== "string"){ -const err80 = {instancePath:instancePath+"/code/foreground",schemaPath:"#/properties/code/properties/foreground/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -} -if(data38.background !== undefined){ -if(typeof data38.background !== "string"){ -const err81 = {instancePath:instancePath+"/code/background",schemaPath:"#/properties/code/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -} -if(data38.tokens !== undefined){ -let data41 = data38.tokens; -if(data41 && typeof data41 == "object" && !Array.isArray(data41)){ -for(const key0 in data41){ -let data42 = data41[key0]; -if(data42 && typeof data42 == "object" && !Array.isArray(data42)){ -if(data42.color === undefined){ -const err82 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "color"},message:"must have required property '"+"color"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data42.background === undefined){ -const err83 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "background"},message:"must have required property '"+"background"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data42.bold === undefined){ -const err84 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "bold"},message:"must have required property '"+"bold"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data42.italic === undefined){ -const err85 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "italic"},message:"must have required property '"+"italic"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data42.underline === undefined){ -const err86 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/required",keyword:"required",params:{missingProperty: "underline"},message:"must have required property '"+"underline"+"'"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(data42.color !== undefined){ -if(typeof data42.color !== "string"){ -const err87 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/color",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/color/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data42.background !== undefined){ -if(typeof data42.background !== "string"){ -const err88 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/background",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data42.bold !== undefined){ -if(typeof data42.bold !== "boolean"){ -const err89 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/bold",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/bold/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data42.italic !== undefined){ -if(typeof data42.italic !== "boolean"){ -const err90 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/italic",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/italic/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data42.underline !== undefined){ -if(typeof data42.underline !== "boolean"){ -const err91 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1")+"/underline",schemaPath:"#/properties/code/properties/tokens/additionalProperties/properties/underline/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -} -else { -const err92 = {instancePath:instancePath+"/code/tokens/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/code/properties/tokens/additionalProperties/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -else { -const err93 = {instancePath:instancePath+"/code/tokens",schemaPath:"#/properties/code/properties/tokens/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -} -else { -const err94 = {instancePath:instancePath+"/code",schemaPath:"#/properties/code/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data.web !== undefined){ -let data48 = data.web; -if((data48 !== null) && (!(data48 && typeof data48 == "object" && !Array.isArray(data48)))){ -const err95 = {instancePath:instancePath+"/web",schemaPath:"#/properties/web/type",keyword:"type",params:{type: schema151.properties.web.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -if(data48 && typeof data48 == "object" && !Array.isArray(data48)){ -if(data48.navigation !== undefined){ -if(typeof data48.navigation !== "string"){ -const err96 = {instancePath:instancePath+"/web/navigation",schemaPath:"#/properties/web/properties/navigation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data48.quiet_border !== undefined){ -if(typeof data48.quiet_border !== "string"){ -const err97 = {instancePath:instancePath+"/web/quiet_border",schemaPath:"#/properties/web/properties/quiet_border/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -if(data48.code_background !== undefined){ -if(typeof data48.code_background !== "string"){ -const err98 = {instancePath:instancePath+"/web/code_background",schemaPath:"#/properties/web/properties/code_background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data48.inline_code_background !== undefined){ -if(typeof data48.inline_code_background !== "string"){ -const err99 = {instancePath:instancePath+"/web/inline_code_background",schemaPath:"#/properties/web/properties/inline_code_background/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -} -} -} -else { -const err100 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -validate150.errors = vErrors; -return errors === 0; -} - -export const RestartNotice = validate151; -const schema152 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cursors":{"type":"object","additionalProperties":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}}},"$id":"https://whip.dev/protocol/v6/RestartNotice","$schema":"http://json-schema.org/draft-07/schema#","title":"RestartNotice","required":["generation","cursors"],"additionalProperties":true}; - -function validate151(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RestartNotice" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursors === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursors"},message:"must have required property '"+"cursors"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err2 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -else { -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cursors !== undefined){ -let data1 = data.cursors; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key0 in data1){ -let data2 = data1[key0]; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err5 = {instancePath:instancePath+"/cursors/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err6 = {instancePath:instancePath+"/cursors/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/cursors/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/cursors/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath:instancePath+"/cursors",schemaPath:"#/properties/cursors/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate151.errors = vErrors; -return errors === 0; -} - -export const RestartParams = validate152; -const schema153 = {"type":"object","properties":{"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/RestartParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RestartParams","required":["generation"],"additionalProperties":true}; - -function validate152(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RestartParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.generation === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation !== undefined){ -let data0 = data.generation; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err1 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err2 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -else { -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate152.errors = vErrors; -return errors === 0; -} - -export const RewindParams = validate153; -const schema154 = {"type":"object","properties":{"expected_revision":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cut":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RewindParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RewindParams","required":["expected_revision","cut"],"additionalProperties":true}; - -function validate153(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RewindParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.expected_revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_revision"},message:"must have required property '"+"expected_revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cut === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cut"},message:"must have required property '"+"cut"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.expected_revision !== undefined){ -let data0 = data.expected_revision; -if((typeof data0 !== "string") && (data0 !== null)){ -const err2 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/type",keyword:"type",params:{type: schema154.properties.expected_revision.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/expected_revision",schemaPath:"#/properties/expected_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -if(data.cut !== undefined){ -let data1 = data.cut; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err5 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate153.errors = vErrors; -return errors === 0; -} - -export const RewindResult = validate154; -const schema155 = {"type":"object","properties":{"cut":{"type":"integer"},"restored_files":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RewindResult","$schema":"http://json-schema.org/draft-07/schema#","title":"RewindResult","required":["cut","restored_files"],"additionalProperties":true}; - -function validate154(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RewindResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cut === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cut"},message:"must have required property '"+"cut"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.restored_files === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "restored_files"},message:"must have required property '"+"restored_files"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cut !== undefined){ -let data0 = data.cut; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err2 = {instancePath:instancePath+"/cut",schemaPath:"#/properties/cut/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.restored_files !== undefined){ -let data1 = data.restored_files; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err3 = {instancePath:instancePath+"/restored_files",schemaPath:"#/properties/restored_files/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate154.errors = vErrors; -return errors === 0; -} - -export const RootCollectionPage = validate155; -const schema156 = {"type":"object","properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"event_cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"allOf":[{"type":"object","properties":{"agent":{"type":["null","object"],"properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":true},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":true},"inbox":{"type":["null","object"],"properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["kind","content"],"additionalProperties":true}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":true},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":true},"blackboard":{"type":["null","object"],"properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["key","version","author_agent_id","payload"],"additionalProperties":true},"budget":{"type":["null","object"],"properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":true}},"required":["agent_id","state"],"additionalProperties":true},"capability":{"type":["null","object"],"properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":true}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":true},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":true},"schedule":{"type":["null","object"],"properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":true},"permission":{"type":["null","object"],"properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":true},"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"additionalProperties":true},{"oneOf":[{"type":"object","properties":{"agent":{"type":["null","object"],"properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":true},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":true}},"required":["agent"],"additionalProperties":true},{"type":"object","properties":{"inbox":{"type":["null","object"],"properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["kind","content"],"additionalProperties":true}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":true},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":true}},"required":["inbox"],"additionalProperties":true},{"type":"object","properties":{"blackboard":{"type":["null","object"],"properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["key","version","author_agent_id","payload"],"additionalProperties":true}},"required":["blackboard"],"additionalProperties":true},{"type":"object","properties":{"budget":{"type":["null","object"],"properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":true}},"required":["agent_id","state"],"additionalProperties":true}},"required":["budget"],"additionalProperties":true},{"type":"object","properties":{"capability":{"type":["null","object"],"properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":true}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":true},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":true}},"required":["capability"],"additionalProperties":true},{"type":"object","properties":{"schedule":{"type":["null","object"],"properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":true}},"required":["schedule"],"additionalProperties":true},{"type":"object","properties":{"permission":{"type":["null","object"],"properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":true}},"required":["permission"],"additionalProperties":true},{"type":"object","properties":{"body":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["body"],"additionalProperties":true}]}]}},"next_cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","collection","revision","offset"],"additionalProperties":true},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/RootCollectionPage","$schema":"http://json-schema.org/draft-07/schema#","title":"RootCollectionPage","required":["root_id","collection","revision","event_cursor","items","has_more"],"additionalProperties":true}; - -function validate155(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootCollectionPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.collection === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.event_cursor === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "event_cursor"},message:"must have required property '"+"event_cursor"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.items === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.has_more === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err6 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.collection !== undefined){ -if(typeof data.collection !== "string"){ -const err7 = {instancePath:instancePath+"/collection",schemaPath:"#/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.revision !== undefined){ -let data2 = data.revision; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err8 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err9 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.event_cursor !== undefined){ -let data3 = data.event_cursor; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err11 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err12 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -else { -const err13 = {instancePath:instancePath+"/event_cursor",schemaPath:"#/properties/event_cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.items !== undefined){ -let data4 = data.items; -if((data4 !== null) && (!(Array.isArray(data4)))){ -const err14 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema156.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(Array.isArray(data4)){ -const len0 = data4.length; -for(let i0=0; i0<len0; i0++){ -let data5 = data4[i0]; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.agent !== undefined){ -let data6 = data5.agent; -if((data6 !== null) && (!(data6 && typeof data6 == "object" && !Array.isArray(data6)))){ -const err15 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data6 && typeof data6 == "object" && !Array.isArray(data6)){ -if(data6.execution_engine === undefined){ -const err16 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data6.id === undefined){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data6.root_id === undefined){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data6.parent_id === undefined){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data6.name === undefined){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data6.model === undefined){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data6.provider === undefined){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(data6.effort === undefined){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data6.cwd === undefined){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data6.report === undefined){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data6.status === undefined){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data6.pending_mail === undefined){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data6.lifecycle_phase === undefined){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data6.blocking_reason === undefined){ -const err29 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data6.terminal_cause === undefined){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data6.allowed_controls === undefined){ -const err31 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data6.execution_engine !== undefined){ -if(typeof data6.execution_engine !== "string"){ -const err32 = {instancePath:instancePath+"/items/" + i0+"/agent/execution_engine",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data6.last_turn !== undefined){ -let data8 = data6.last_turn; -if((data8 !== null) && (!(data8 && typeof data8 == "object" && !Array.isArray(data8)))){ -const err33 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.status === undefined){ -const err34 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data8.event_seq === undefined){ -const err35 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data8.turn_id !== undefined){ -if(typeof data8.turn_id !== "string"){ -const err36 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/turn_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data8.status !== undefined){ -if(typeof data8.status !== "string"){ -const err37 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/status",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data8.started_at !== undefined){ -if(typeof data8.started_at !== "string"){ -const err38 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/started_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data8.finished_at !== undefined){ -if(typeof data8.finished_at !== "string"){ -const err39 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/finished_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data8.event_seq !== undefined){ -let data13 = data8.event_seq; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err40 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err41 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data8.error !== undefined){ -if(typeof data8.error !== "string"){ -const err43 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data8.error_truncated !== undefined){ -if(typeof data8.error_truncated !== "boolean"){ -const err44 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_truncated",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data8.error_details !== undefined){ -let data16 = data8.error_details; -if((data16 !== null) && (!(data16 && typeof data16 == "object" && !Array.isArray(data16)))){ -const err45 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data16 && typeof data16 == "object" && !Array.isArray(data16)){ -if(data16.reference_id === undefined){ -const err46 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data16.digest === undefined){ -const err47 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data16.size === undefined){ -const err48 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data16.media_type === undefined){ -const err49 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data16.source === undefined){ -const err50 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data16.text !== undefined){ -let data17 = data16.text; -if((data17 !== null) && (typeof data17 !== "string")){ -const err51 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/text",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -} -if(data16.binary !== undefined){ -let data18 = data16.binary; -if((typeof data18 !== "string") && (data18 !== null)){ -const err52 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -} -if(data16.reference_id !== undefined){ -if(typeof data16.reference_id !== "string"){ -const err53 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -} -if(data16.digest !== undefined){ -if(typeof data16.digest !== "string"){ -const err54 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data16.size !== undefined){ -let data21 = data16.size; -if(typeof data21 === "string"){ -if(!pattern0.test(data21)){ -const err55 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -if(!(formats0.validate(data21))){ -const err56 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -else { -const err57 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data16.media_type !== undefined){ -if(typeof data16.media_type !== "string"){ -const err58 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data16.source !== undefined){ -if(typeof data16.source !== "string"){ -const err59 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/source",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -} -} -if(data8.model_calls !== undefined){ -let data24 = data8.model_calls; -if(!((typeof data24 == "number") && (!(data24 % 1) && !isNaN(data24)))){ -const err60 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/model_calls",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data8.compactions !== undefined){ -let data25 = data8.compactions; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err61 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/compactions",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data8.last_activity_at !== undefined){ -if(typeof data8.last_activity_at !== "string"){ -const err62 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -} -} -if(data6.id !== undefined){ -if(typeof data6.id !== "string"){ -const err63 = {instancePath:instancePath+"/items/" + i0+"/agent/id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data6.root_id !== undefined){ -if(typeof data6.root_id !== "string"){ -const err64 = {instancePath:instancePath+"/items/" + i0+"/agent/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data6.parent_id !== undefined){ -if(typeof data6.parent_id !== "string"){ -const err65 = {instancePath:instancePath+"/items/" + i0+"/agent/parent_id",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data6.name !== undefined){ -if(typeof data6.name !== "string"){ -const err66 = {instancePath:instancePath+"/items/" + i0+"/agent/name",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -} -if(data6.model !== undefined){ -if(typeof data6.model !== "string"){ -const err67 = {instancePath:instancePath+"/items/" + i0+"/agent/model",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -if(data6.provider !== undefined){ -if(typeof data6.provider !== "string"){ -const err68 = {instancePath:instancePath+"/items/" + i0+"/agent/provider",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data6.effort !== undefined){ -if(typeof data6.effort !== "string"){ -const err69 = {instancePath:instancePath+"/items/" + i0+"/agent/effort",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data6.cwd !== undefined){ -if(typeof data6.cwd !== "string"){ -const err70 = {instancePath:instancePath+"/items/" + i0+"/agent/cwd",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data6.report !== undefined){ -if(typeof data6.report !== "string"){ -const err71 = {instancePath:instancePath+"/items/" + i0+"/agent/report",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data6.status !== undefined){ -if(typeof data6.status !== "string"){ -const err72 = {instancePath:instancePath+"/items/" + i0+"/agent/status",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data6.pending_mail !== undefined){ -let data37 = data6.pending_mail; -if(!((typeof data37 == "number") && (!(data37 % 1) && !isNaN(data37)))){ -const err73 = {instancePath:instancePath+"/items/" + i0+"/agent/pending_mail",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data6.lifecycle_phase !== undefined){ -if(typeof data6.lifecycle_phase !== "string"){ -const err74 = {instancePath:instancePath+"/items/" + i0+"/agent/lifecycle_phase",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data6.blocking_reason !== undefined){ -if(typeof data6.blocking_reason !== "string"){ -const err75 = {instancePath:instancePath+"/items/" + i0+"/agent/blocking_reason",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data6.terminal_cause !== undefined){ -if(typeof data6.terminal_cause !== "string"){ -const err76 = {instancePath:instancePath+"/items/" + i0+"/agent/terminal_cause",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data6.allowed_controls !== undefined){ -let data41 = data6.allowed_controls; -if((data41 !== null) && (!(Array.isArray(data41)))){ -const err77 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls",schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(Array.isArray(data41)){ -const len1 = data41.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data41[i1] !== "string"){ -const err78 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls/" + i1,schemaPath:"#/properties/items/items/allOf/0/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -} -} -} -} -if(data5.inbox !== undefined){ -let data43 = data5.inbox; -if((data43 !== null) && (!(data43 && typeof data43 == "object" && !Array.isArray(data43)))){ -const err79 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data43 && typeof data43 == "object" && !Array.isArray(data43)){ -if(data43.root_id === undefined){ -const err80 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(data43.agent_id === undefined){ -const err81 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data43.seq === undefined){ -const err82 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data43.kind === undefined){ -const err83 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data43.status === undefined){ -const err84 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data43.payload === undefined){ -const err85 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data43.delivery_seq !== undefined){ -let data44 = data43.delivery_seq; -if(typeof data44 === "string"){ -if(!pattern0.test(data44)){ -const err86 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -if(!(formats0.validate(data44))){ -const err87 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -else { -const err88 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -} -if(data43.origin !== undefined){ -if(typeof data43.origin !== "string"){ -const err89 = {instancePath:instancePath+"/items/" + i0+"/inbox/origin",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -} -if(data43.command_client_id !== undefined){ -if(typeof data43.command_client_id !== "string"){ -const err90 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_client_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data43.command_id !== undefined){ -if(typeof data43.command_id !== "string"){ -const err91 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -if(data43.steer_turn_id !== undefined){ -if(typeof data43.steer_turn_id !== "string"){ -const err92 = {instancePath:instancePath+"/items/" + i0+"/inbox/steer_turn_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -if(data43.preview !== undefined){ -let data49 = data43.preview; -if((data49 !== null) && (!(data49 && typeof data49 == "object" && !Array.isArray(data49)))){ -const err93 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -if(data49 && typeof data49 == "object" && !Array.isArray(data49)){ -if(data49.text === undefined){ -const err94 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -if(data49.design_context !== undefined){ -let data50 = data49.design_context; -if((data50 !== null) && (!(data50 && typeof data50 == "object" && !Array.isArray(data50)))){ -const err95 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -if(data50 && typeof data50 == "object" && !Array.isArray(data50)){ -if(data50.context_attachment_id === undefined){ -const err96 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -if(data50.elements === undefined){ -const err97 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -if(data50.element_count === undefined){ -const err98 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -if(data50.context_attachment_id !== undefined){ -if(typeof data50.context_attachment_id !== "string"){ -const err99 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/context_attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data50.screenshot_attachment_id !== undefined){ -if(typeof data50.screenshot_attachment_id !== "string"){ -const err100 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -} -if(data50.elements !== undefined){ -let data53 = data50.elements; -if((data53 !== null) && (!(Array.isArray(data53)))){ -const err101 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(Array.isArray(data53)){ -const len2 = data53.length; -for(let i2=0; i2<len2; i2++){ -let data54 = data53[i2]; -if(data54 && typeof data54 == "object" && !Array.isArray(data54)){ -if(data54.label === undefined){ -const err102 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(data54.label !== undefined){ -if(typeof data54.label !== "string"){ -const err103 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2+"/label",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data54.selector !== undefined){ -if(typeof data54.selector !== "string"){ -const err104 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2+"/selector",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -} -else { -const err105 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i2,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -} -} -if(data50.element_count !== undefined){ -let data57 = data50.element_count; -if(!((typeof data57 == "number") && (!(data57 % 1) && !isNaN(data57)))){ -const err106 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/element_count",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data50.page_url !== undefined){ -if(typeof data50.page_url !== "string"){ -const err107 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_url",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data50.page_title !== undefined){ -if(typeof data50.page_title !== "string"){ -const err108 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_title",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -} -} -if(data49.text !== undefined){ -if(typeof data49.text !== "string"){ -const err109 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data49.truncated !== undefined){ -if(typeof data49.truncated !== "boolean"){ -const err110 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/truncated",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data49.attachments !== undefined){ -let data62 = data49.attachments; -if((data62 !== null) && (!(Array.isArray(data62)))){ -const err111 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -if(Array.isArray(data62)){ -const len3 = data62.length; -for(let i3=0; i3<len3; i3++){ -let data63 = data62[i3]; -if(data63 && typeof data63 == "object" && !Array.isArray(data63)){ -if(data63.kind === undefined){ -const err112 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -if(data63.content === undefined){ -const err113 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(data63.kind !== undefined){ -if(typeof data63.kind !== "string"){ -const err114 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/kind",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -} -if(data63.name !== undefined){ -if(typeof data63.name !== "string"){ -const err115 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/name",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data63.content !== undefined){ -let data66 = data63.content; -if(data66 && typeof data66 == "object" && !Array.isArray(data66)){ -if(data66.reference_id === undefined){ -const err116 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -if(data66.digest === undefined){ -const err117 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -if(data66.size === undefined){ -const err118 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -if(data66.media_type === undefined){ -const err119 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -if(data66.source === undefined){ -const err120 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -if(data66.text !== undefined){ -let data67 = data66.text; -if((data67 !== null) && (typeof data67 !== "string")){ -const err121 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -} -if(data66.binary !== undefined){ -let data68 = data66.binary; -if((typeof data68 !== "string") && (data68 !== null)){ -const err122 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/binary",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data66.reference_id !== undefined){ -if(typeof data66.reference_id !== "string"){ -const err123 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data66.digest !== undefined){ -if(typeof data66.digest !== "string"){ -const err124 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/digest",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data66.size !== undefined){ -let data71 = data66.size; -if(typeof data71 === "string"){ -if(!pattern0.test(data71)){ -const err125 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -if(!(formats0.validate(data71))){ -const err126 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -else { -const err127 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -if(data66.media_type !== undefined){ -if(typeof data66.media_type !== "string"){ -const err128 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -if(data66.source !== undefined){ -if(typeof data66.source !== "string"){ -const err129 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content/source",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -} -else { -const err130 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3+"/content",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -} -else { -const err131 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i3,schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -} -} -if(data49.attachment_count !== undefined){ -let data74 = data49.attachment_count; -if(!((typeof data74 == "number") && (!(data74 % 1) && !isNaN(data74)))){ -const err132 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachment_count",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -} -} -} -if(data43.root_id !== undefined){ -if(typeof data43.root_id !== "string"){ -const err133 = {instancePath:instancePath+"/items/" + i0+"/inbox/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -} -if(data43.agent_id !== undefined){ -if(typeof data43.agent_id !== "string"){ -const err134 = {instancePath:instancePath+"/items/" + i0+"/inbox/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data43.seq !== undefined){ -let data77 = data43.seq; -if(typeof data77 === "string"){ -if(!pattern0.test(data77)){ -const err135 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -if(!(formats0.validate(data77))){ -const err136 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -} -else { -const err137 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -} -if(data43.kind !== undefined){ -if(typeof data43.kind !== "string"){ -const err138 = {instancePath:instancePath+"/items/" + i0+"/inbox/kind",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -if(data43.status !== undefined){ -if(typeof data43.status !== "string"){ -const err139 = {instancePath:instancePath+"/items/" + i0+"/inbox/status",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -if(data43.payload !== undefined){ -let data80 = data43.payload; -if(data80 && typeof data80 == "object" && !Array.isArray(data80)){ -if(data80.reference_id === undefined){ -const err140 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -if(data80.digest === undefined){ -const err141 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -if(data80.size === undefined){ -const err142 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -if(data80.media_type === undefined){ -const err143 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -if(data80.source === undefined){ -const err144 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(data80.text !== undefined){ -let data81 = data80.text; -if((data81 !== null) && (typeof data81 !== "string")){ -const err145 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/text",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -} -if(data80.binary !== undefined){ -let data82 = data80.binary; -if((typeof data82 !== "string") && (data82 !== null)){ -const err146 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/binary",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.inbox.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -} -if(data80.reference_id !== undefined){ -if(typeof data80.reference_id !== "string"){ -const err147 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -} -if(data80.digest !== undefined){ -if(typeof data80.digest !== "string"){ -const err148 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/digest",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data80.size !== undefined){ -let data85 = data80.size; -if(typeof data85 === "string"){ -if(!pattern0.test(data85)){ -const err149 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -if(!(formats0.validate(data85))){ -const err150 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -} -else { -const err151 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -} -if(data80.media_type !== undefined){ -if(typeof data80.media_type !== "string"){ -const err152 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data80.source !== undefined){ -if(typeof data80.source !== "string"){ -const err153 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/source",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -} -else { -const err154 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/0/properties/inbox/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -} -} -} -if(data5.blackboard !== undefined){ -let data88 = data5.blackboard; -if((data88 !== null) && (!(data88 && typeof data88 == "object" && !Array.isArray(data88)))){ -const err155 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -if(data88 && typeof data88 == "object" && !Array.isArray(data88)){ -if(data88.key === undefined){ -const err156 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -if(data88.version === undefined){ -const err157 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -if(data88.author_agent_id === undefined){ -const err158 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -if(data88.payload === undefined){ -const err159 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -if(data88.key !== undefined){ -if(typeof data88.key !== "string"){ -const err160 = {instancePath:instancePath+"/items/" + i0+"/blackboard/key",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data88.version !== undefined){ -let data90 = data88.version; -if(typeof data90 === "string"){ -if(!pattern0.test(data90)){ -const err161 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -if(!(formats0.validate(data90))){ -const err162 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -} -else { -const err163 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -} -if(data88.author_agent_id !== undefined){ -if(typeof data88.author_agent_id !== "string"){ -const err164 = {instancePath:instancePath+"/items/" + i0+"/blackboard/author_agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -} -if(data88.payload !== undefined){ -let data92 = data88.payload; -if(data92 && typeof data92 == "object" && !Array.isArray(data92)){ -if(data92.reference_id === undefined){ -const err165 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -if(data92.digest === undefined){ -const err166 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -if(data92.size === undefined){ -const err167 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -if(data92.media_type === undefined){ -const err168 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -if(data92.source === undefined){ -const err169 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -if(data92.text !== undefined){ -let data93 = data92.text; -if((data93 !== null) && (typeof data93 !== "string")){ -const err170 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/text",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -} -if(data92.binary !== undefined){ -let data94 = data92.binary; -if((typeof data94 !== "string") && (data94 !== null)){ -const err171 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/binary",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.blackboard.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -} -if(data92.reference_id !== undefined){ -if(typeof data92.reference_id !== "string"){ -const err172 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -} -if(data92.digest !== undefined){ -if(typeof data92.digest !== "string"){ -const err173 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/digest",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -} -if(data92.size !== undefined){ -let data97 = data92.size; -if(typeof data97 === "string"){ -if(!pattern0.test(data97)){ -const err174 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -if(!(formats0.validate(data97))){ -const err175 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -} -else { -const err176 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -} -if(data92.media_type !== undefined){ -if(typeof data92.media_type !== "string"){ -const err177 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -if(data92.source !== undefined){ -if(typeof data92.source !== "string"){ -const err178 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/source",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -} -else { -const err179 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/0/properties/blackboard/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -} -} -} -if(data5.budget !== undefined){ -let data100 = data5.budget; -if((data100 !== null) && (!(data100 && typeof data100 == "object" && !Array.isArray(data100)))){ -const err180 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -if(data100 && typeof data100 == "object" && !Array.isArray(data100)){ -if(data100.agent_id === undefined){ -const err181 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -if(data100.state === undefined){ -const err182 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/0/properties/budget/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -if(data100.agent_id !== undefined){ -if(typeof data100.agent_id !== "string"){ -const err183 = {instancePath:instancePath+"/items/" + i0+"/budget/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -} -if(data100.state !== undefined){ -let data102 = data100.state; -if(data102 && typeof data102 == "object" && !Array.isArray(data102)){ -if(data102.kind === undefined){ -const err184 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -if(data102.limit === undefined){ -const err185 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -if(data102.used === undefined){ -const err186 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -if(data102.reserved === undefined){ -const err187 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -if(data102.remaining === undefined){ -const err188 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -if(data102.uncertain === undefined){ -const err189 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -if(data102.incomplete === undefined){ -const err190 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -if(data102.kind !== undefined){ -if(typeof data102.kind !== "string"){ -const err191 = {instancePath:instancePath+"/items/" + i0+"/budget/state/kind",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -} -if(data102.limit !== undefined){ -let data104 = data102.limit; -if((typeof data104 !== "string") && (data104 !== null)){ -const err192 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -if(typeof data104 === "string"){ -if(!pattern0.test(data104)){ -const err193 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -if(!(formats0.validate(data104))){ -const err194 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -} -} -if(data102.used !== undefined){ -let data105 = data102.used; -if(typeof data105 === "string"){ -if(!pattern0.test(data105)){ -const err195 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -if(!(formats0.validate(data105))){ -const err196 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -} -else { -const err197 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -} -if(data102.reserved !== undefined){ -let data106 = data102.reserved; -if(typeof data106 === "string"){ -if(!pattern0.test(data106)){ -const err198 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -if(!(formats0.validate(data106))){ -const err199 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -} -else { -const err200 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -} -if(data102.remaining !== undefined){ -let data107 = data102.remaining; -if((typeof data107 !== "string") && (data107 !== null)){ -const err201 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.budget.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -if(typeof data107 === "string"){ -if(!pattern0.test(data107)){ -const err202 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -if(!(formats0.validate(data107))){ -const err203 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -} -} -if(data102.uncertain !== undefined){ -let data108 = data102.uncertain; -if(typeof data108 === "string"){ -if(!pattern0.test(data108)){ -const err204 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -if(!(formats0.validate(data108))){ -const err205 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -} -else { -const err206 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -} -if(data102.incomplete !== undefined){ -if(typeof data102.incomplete !== "boolean"){ -const err207 = {instancePath:instancePath+"/items/" + i0+"/budget/state/incomplete",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -} -} -else { -const err208 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/0/properties/budget/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -} -} -} -if(data5.capability !== undefined){ -let data110 = data5.capability; -if((data110 !== null) && (!(data110 && typeof data110 == "object" && !Array.isArray(data110)))){ -const err209 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -if(data110 && typeof data110 == "object" && !Array.isArray(data110)){ -if(data110.id === undefined){ -const err210 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -if(data110.root_id === undefined){ -const err211 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -if(data110.agent_id === undefined){ -const err212 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -if(data110.issuer_agent_id === undefined){ -const err213 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -if(data110.operations === undefined){ -const err214 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -if(data110.scopes === undefined){ -const err215 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -if(data110.mcp === undefined){ -const err216 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -if(data110.mcp_all === undefined){ -const err217 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -if(data110.generation === undefined){ -const err218 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -if(data110.status === undefined){ -const err219 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -if(data110.expires_at === undefined){ -const err220 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -if(data110.created_at === undefined){ -const err221 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -if(data110.updated_at === undefined){ -const err222 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/0/properties/capability/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -if(data110.id !== undefined){ -if(typeof data110.id !== "string"){ -const err223 = {instancePath:instancePath+"/items/" + i0+"/capability/id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -} -if(data110.root_id !== undefined){ -if(typeof data110.root_id !== "string"){ -const err224 = {instancePath:instancePath+"/items/" + i0+"/capability/root_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -} -if(data110.agent_id !== undefined){ -if(typeof data110.agent_id !== "string"){ -const err225 = {instancePath:instancePath+"/items/" + i0+"/capability/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -} -if(data110.issuer_agent_id !== undefined){ -if(typeof data110.issuer_agent_id !== "string"){ -const err226 = {instancePath:instancePath+"/items/" + i0+"/capability/issuer_agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -} -if(data110.operations !== undefined){ -let data115 = data110.operations; -if((data115 !== null) && (!(Array.isArray(data115)))){ -const err227 = {instancePath:instancePath+"/items/" + i0+"/capability/operations",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/operations/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -if(Array.isArray(data115)){ -const len4 = data115.length; -for(let i4=0; i4<len4; i4++){ -if(typeof data115[i4] !== "string"){ -const err228 = {instancePath:instancePath+"/items/" + i0+"/capability/operations/" + i4,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -} -} -} -if(data110.scopes !== undefined){ -let data117 = data110.scopes; -if((data117 !== null) && (!(Array.isArray(data117)))){ -const err229 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/scopes/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -if(Array.isArray(data117)){ -const len5 = data117.length; -for(let i5=0; i5<len5; i5++){ -if(typeof data117[i5] !== "string"){ -const err230 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes/" + i5,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -} -} -} -if(data110.file_scope !== undefined){ -if(typeof data110.file_scope !== "string"){ -const err231 = {instancePath:instancePath+"/items/" + i0+"/capability/file_scope",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -} -if(data110.file_issuer_id !== undefined){ -if(typeof data110.file_issuer_id !== "string"){ -const err232 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -} -if(data110.file_issuer_generation !== undefined){ -let data121 = data110.file_issuer_generation; -if(typeof data121 === "string"){ -if(!pattern0.test(data121)){ -const err233 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -if(!(formats0.validate(data121))){ -const err234 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -} -else { -const err235 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -} -if(data110.mcp !== undefined){ -let data122 = data110.mcp; -if((data122 !== null) && (!(Array.isArray(data122)))){ -const err236 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -if(Array.isArray(data122)){ -const len6 = data122.length; -for(let i6=0; i6<len6; i6++){ -let data123 = data122[i6]; -if(data123 && typeof data123 == "object" && !Array.isArray(data123)){ -if(data123.server === undefined){ -const err237 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -if(data123.tool === undefined){ -const err238 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -if(data123.definition === undefined){ -const err239 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -if(data123.server !== undefined){ -if(typeof data123.server !== "string"){ -const err240 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/server",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data123.tool !== undefined){ -if(typeof data123.tool !== "string"){ -const err241 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/tool",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data123.definition !== undefined){ -if(typeof data123.definition !== "string"){ -const err242 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6+"/definition",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -} -} -else { -const err243 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i6,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -} -} -} -if(data110.mcp_all !== undefined){ -if(typeof data110.mcp_all !== "boolean"){ -const err244 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp_all",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -} -if(data110.browser !== undefined){ -let data128 = data110.browser; -if((data128 !== null) && (!(data128 && typeof data128 == "object" && !Array.isArray(data128)))){ -const err245 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -if(data128 && typeof data128 == "object" && !Array.isArray(data128)){ -if(data128.provider_id === undefined){ -const err246 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -if(data128.provider_epoch === undefined){ -const err247 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -if(data128.tab_id === undefined){ -const err248 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -if(data128.tab_generation === undefined){ -const err249 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -if(data128.profile_id === undefined){ -const err250 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -if(data128.rights === undefined){ -const err251 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -if(data128.provider_id !== undefined){ -if(typeof data128.provider_id !== "string"){ -const err252 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -} -if(data128.provider_epoch !== undefined){ -if(typeof data128.provider_epoch !== "string"){ -const err253 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_epoch",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -} -if(data128.tab_id !== undefined){ -if(typeof data128.tab_id !== "string"){ -const err254 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -} -if(data128.tab_generation !== undefined){ -if(typeof data128.tab_generation !== "string"){ -const err255 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -} -if(data128.profile_id !== undefined){ -if(typeof data128.profile_id !== "string"){ -const err256 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/profile_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -} -if(data128.attachment_id !== undefined){ -if(typeof data128.attachment_id !== "string"){ -const err257 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -} -if(data128.attachment_generation !== undefined){ -if(typeof data128.attachment_generation !== "string"){ -const err258 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -} -if(data128.rights !== undefined){ -let data136 = data128.rights; -if((data136 !== null) && (!(Array.isArray(data136)))){ -const err259 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/rights/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -if(Array.isArray(data136)){ -const len7 = data136.length; -for(let i7=0; i7<len7; i7++){ -if(typeof data136[i7] !== "string"){ -const err260 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights/" + i7,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -} -} -} -if(data128.preview !== undefined){ -let data138 = data128.preview; -if((data138 !== null) && (!(data138 && typeof data138 == "object" && !Array.isArray(data138)))){ -const err261 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -if(data138 && typeof data138 == "object" && !Array.isArray(data138)){ -if(data138.host_id === undefined){ -const err262 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -if(data138.host_identity === undefined){ -const err263 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -if(data138.connection_generation === undefined){ -const err264 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -if(data138.environment_id === undefined){ -const err265 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -if(data138.loopback === undefined){ -const err266 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -if(data138.ports === undefined){ -const err267 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -if(data138.host_id !== undefined){ -if(typeof data138.host_id !== "string"){ -const err268 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -} -if(data138.host_identity !== undefined){ -if(typeof data138.host_identity !== "string"){ -const err269 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_identity",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -} -if(data138.connection_generation !== undefined){ -if(typeof data138.connection_generation !== "string"){ -const err270 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/connection_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -} -if(data138.environment_id !== undefined){ -if(typeof data138.environment_id !== "string"){ -const err271 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/environment_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -} -if(data138.loopback !== undefined){ -if(typeof data138.loopback !== "string"){ -const err272 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/loopback",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -} -if(data138.ports !== undefined){ -let data144 = data138.ports; -if((data144 !== null) && (!(Array.isArray(data144)))){ -const err273 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.capability.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -if(Array.isArray(data144)){ -const len8 = data144.length; -for(let i8=0; i8<len8; i8++){ -let data145 = data144[i8]; -if(!((typeof data145 == "number") && (!(data145 % 1) && !isNaN(data145)))){ -const err274 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports/" + i8,schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -} -} -} -} -} -} -} -if(data110.browser_issuer_id !== undefined){ -if(typeof data110.browser_issuer_id !== "string"){ -const err275 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_id",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -} -if(data110.browser_issuer_generation !== undefined){ -let data147 = data110.browser_issuer_generation; -if(!((typeof data147 == "number") && (!(data147 % 1) && !isNaN(data147)))){ -const err276 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -} -if(data110.browser_delegation_only !== undefined){ -if(typeof data110.browser_delegation_only !== "boolean"){ -const err277 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_delegation_only",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -} -if(data110.generation !== undefined){ -let data149 = data110.generation; -if(typeof data149 === "string"){ -if(!pattern0.test(data149)){ -const err278 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -if(!(formats0.validate(data149))){ -const err279 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -} -else { -const err280 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -} -if(data110.status !== undefined){ -if(typeof data110.status !== "string"){ -const err281 = {instancePath:instancePath+"/items/" + i0+"/capability/status",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -} -if(data110.expires_at !== undefined){ -if(typeof data110.expires_at !== "string"){ -const err282 = {instancePath:instancePath+"/items/" + i0+"/capability/expires_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -} -if(data110.created_at !== undefined){ -if(typeof data110.created_at !== "string"){ -const err283 = {instancePath:instancePath+"/items/" + i0+"/capability/created_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -} -if(data110.updated_at !== undefined){ -if(typeof data110.updated_at !== "string"){ -const err284 = {instancePath:instancePath+"/items/" + i0+"/capability/updated_at",schemaPath:"#/properties/items/items/allOf/0/properties/capability/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -} -} -} -if(data5.schedule !== undefined){ -let data154 = data5.schedule; -if((data154 !== null) && (!(data154 && typeof data154 == "object" && !Array.isArray(data154)))){ -const err285 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.schedule.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -if(data154 && typeof data154 == "object" && !Array.isArray(data154)){ -if(data154.id === undefined){ -const err286 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -if(data154.schedule === undefined){ -const err287 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -if(data154.prompt === undefined){ -const err288 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -if(data154.anchor === undefined){ -const err289 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -if(data154.last_fire === undefined){ -const err290 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -if(data154.id !== undefined){ -let data155 = data154.id; -if(!((typeof data155 == "number") && (!(data155 % 1) && !isNaN(data155)))){ -const err291 = {instancePath:instancePath+"/items/" + i0+"/schedule/id",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data154.schedule !== undefined){ -if(typeof data154.schedule !== "string"){ -const err292 = {instancePath:instancePath+"/items/" + i0+"/schedule/schedule",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -} -if(data154.prompt !== undefined){ -if(typeof data154.prompt !== "string"){ -const err293 = {instancePath:instancePath+"/items/" + i0+"/schedule/prompt",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -} -if(data154.anchor !== undefined){ -if(typeof data154.anchor !== "string"){ -const err294 = {instancePath:instancePath+"/items/" + i0+"/schedule/anchor",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -} -if(data154.last_fire !== undefined){ -if(typeof data154.last_fire !== "string"){ -const err295 = {instancePath:instancePath+"/items/" + i0+"/schedule/last_fire",schemaPath:"#/properties/items/items/allOf/0/properties/schedule/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -} -} -} -if(data5.permission !== undefined){ -let data160 = data5.permission; -if((data160 !== null) && (!(data160 && typeof data160 == "object" && !Array.isArray(data160)))){ -const err296 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.permission.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -if(data160 && typeof data160 == "object" && !Array.isArray(data160)){ -if(data160.id === undefined){ -const err297 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -if(data160.agent_id === undefined){ -const err298 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -if(data160.operation_id === undefined){ -const err299 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -if(data160.operation === undefined){ -const err300 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -if(data160.canonical_path === undefined){ -const err301 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -if(data160.request_digest === undefined){ -const err302 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -if(data160.capability_id === undefined){ -const err303 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -if(data160.capability_generation === undefined){ -const err304 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -if(data160.status === undefined){ -const err305 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -if(data160.command === undefined){ -const err306 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -if(data160.rule === undefined){ -const err307 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/0/properties/permission/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -if(data160.id !== undefined){ -if(typeof data160.id !== "string"){ -const err308 = {instancePath:instancePath+"/items/" + i0+"/permission/id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -} -if(data160.agent_id !== undefined){ -if(typeof data160.agent_id !== "string"){ -const err309 = {instancePath:instancePath+"/items/" + i0+"/permission/agent_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -} -if(data160.operation_id !== undefined){ -if(typeof data160.operation_id !== "string"){ -const err310 = {instancePath:instancePath+"/items/" + i0+"/permission/operation_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -} -if(data160.operation !== undefined){ -if(typeof data160.operation !== "string"){ -const err311 = {instancePath:instancePath+"/items/" + i0+"/permission/operation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -} -if(data160.canonical_path !== undefined){ -if(typeof data160.canonical_path !== "string"){ -const err312 = {instancePath:instancePath+"/items/" + i0+"/permission/canonical_path",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -} -if(data160.request_digest !== undefined){ -if(typeof data160.request_digest !== "string"){ -const err313 = {instancePath:instancePath+"/items/" + i0+"/permission/request_digest",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -} -if(data160.capability_id !== undefined){ -if(typeof data160.capability_id !== "string"){ -const err314 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_id",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -} -if(data160.capability_generation !== undefined){ -let data168 = data160.capability_generation; -if(typeof data168 === "string"){ -if(!pattern0.test(data168)){ -const err315 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -if(!(formats0.validate(data168))){ -const err316 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -} -else { -const err317 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -} -if(data160.status !== undefined){ -if(typeof data160.status !== "string"){ -const err318 = {instancePath:instancePath+"/items/" + i0+"/permission/status",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -} -if(data160.command !== undefined){ -if(typeof data160.command !== "string"){ -const err319 = {instancePath:instancePath+"/items/" + i0+"/permission/command",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -} -if(data160.rule !== undefined){ -if(typeof data160.rule !== "string"){ -const err320 = {instancePath:instancePath+"/items/" + i0+"/permission/rule",schemaPath:"#/properties/items/items/allOf/0/properties/permission/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -} -} -} -if(data5.body !== undefined){ -let data172 = data5.body; -if((data172 !== null) && (!(data172 && typeof data172 == "object" && !Array.isArray(data172)))){ -const err321 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -if(data172 && typeof data172 == "object" && !Array.isArray(data172)){ -if(data172.reference_id === undefined){ -const err322 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -if(data172.digest === undefined){ -const err323 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -if(data172.size === undefined){ -const err324 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -if(data172.media_type === undefined){ -const err325 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -if(data172.source === undefined){ -const err326 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/0/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -if(data172.text !== undefined){ -let data173 = data172.text; -if((data173 !== null) && (typeof data173 !== "string")){ -const err327 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -} -if(data172.binary !== undefined){ -let data174 = data172.binary; -if((typeof data174 !== "string") && (data174 !== null)){ -const err328 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[0].properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -} -if(data172.reference_id !== undefined){ -if(typeof data172.reference_id !== "string"){ -const err329 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -} -if(data172.digest !== undefined){ -if(typeof data172.digest !== "string"){ -const err330 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -} -if(data172.size !== undefined){ -let data177 = data172.size; -if(typeof data177 === "string"){ -if(!pattern0.test(data177)){ -const err331 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -if(!(formats0.validate(data177))){ -const err332 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -} -else { -const err333 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -} -if(data172.media_type !== undefined){ -if(typeof data172.media_type !== "string"){ -const err334 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -} -if(data172.source !== undefined){ -if(typeof data172.source !== "string"){ -const err335 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/allOf/0/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -} -} -} -else { -const err336 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -const _errs386 = errors; -let valid42 = false; -let passing0 = null; -const _errs387 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.agent === undefined){ -const err337 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/required",keyword:"required",params:{missingProperty: "agent"},message:"must have required property '"+"agent"+"'"}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -if(data5.agent !== undefined){ -let data180 = data5.agent; -if((data180 !== null) && (!(data180 && typeof data180 == "object" && !Array.isArray(data180)))){ -const err338 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -if(data180 && typeof data180 == "object" && !Array.isArray(data180)){ -if(data180.execution_engine === undefined){ -const err339 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -if(data180.id === undefined){ -const err340 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -if(data180.root_id === undefined){ -const err341 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -if(data180.parent_id === undefined){ -const err342 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -if(data180.name === undefined){ -const err343 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -if(data180.model === undefined){ -const err344 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -if(data180.provider === undefined){ -const err345 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -if(data180.effort === undefined){ -const err346 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -if(data180.cwd === undefined){ -const err347 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -if(data180.report === undefined){ -const err348 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -if(data180.status === undefined){ -const err349 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -if(data180.pending_mail === undefined){ -const err350 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -if(data180.lifecycle_phase === undefined){ -const err351 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -if(data180.blocking_reason === undefined){ -const err352 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -if(data180.terminal_cause === undefined){ -const err353 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -if(data180.allowed_controls === undefined){ -const err354 = {instancePath:instancePath+"/items/" + i0+"/agent",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -if(data180.execution_engine !== undefined){ -if(typeof data180.execution_engine !== "string"){ -const err355 = {instancePath:instancePath+"/items/" + i0+"/agent/execution_engine",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -} -if(data180.last_turn !== undefined){ -let data182 = data180.last_turn; -if((data182 !== null) && (!(data182 && typeof data182 == "object" && !Array.isArray(data182)))){ -const err356 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -if(data182 && typeof data182 == "object" && !Array.isArray(data182)){ -if(data182.status === undefined){ -const err357 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -if(data182.event_seq === undefined){ -const err358 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -if(data182.turn_id !== undefined){ -if(typeof data182.turn_id !== "string"){ -const err359 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/turn_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -} -if(data182.status !== undefined){ -if(typeof data182.status !== "string"){ -const err360 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -} -if(data182.started_at !== undefined){ -if(typeof data182.started_at !== "string"){ -const err361 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/started_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -} -if(data182.finished_at !== undefined){ -if(typeof data182.finished_at !== "string"){ -const err362 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/finished_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -} -if(data182.event_seq !== undefined){ -let data187 = data182.event_seq; -if(typeof data187 === "string"){ -if(!pattern0.test(data187)){ -const err363 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -if(!(formats0.validate(data187))){ -const err364 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -} -else { -const err365 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/event_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -} -if(data182.error !== undefined){ -if(typeof data182.error !== "string"){ -const err366 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -} -if(data182.error_truncated !== undefined){ -if(typeof data182.error_truncated !== "boolean"){ -const err367 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_truncated",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -} -if(data182.error_details !== undefined){ -let data190 = data182.error_details; -if((data190 !== null) && (!(data190 && typeof data190 == "object" && !Array.isArray(data190)))){ -const err368 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -if(data190 && typeof data190 == "object" && !Array.isArray(data190)){ -if(data190.reference_id === undefined){ -const err369 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -if(data190.digest === undefined){ -const err370 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -if(data190.size === undefined){ -const err371 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -if(data190.media_type === undefined){ -const err372 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -if(data190.source === undefined){ -const err373 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -if(data190.text !== undefined){ -let data191 = data190.text; -if((data191 !== null) && (typeof data191 !== "string")){ -const err374 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -} -if(data190.binary !== undefined){ -let data192 = data190.binary; -if((typeof data192 !== "string") && (data192 !== null)){ -const err375 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -} -if(data190.reference_id !== undefined){ -if(typeof data190.reference_id !== "string"){ -const err376 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -} -if(data190.digest !== undefined){ -if(typeof data190.digest !== "string"){ -const err377 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -} -if(data190.size !== undefined){ -let data195 = data190.size; -if(typeof data195 === "string"){ -if(!pattern0.test(data195)){ -const err378 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -if(!(formats0.validate(data195))){ -const err379 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -} -else { -const err380 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -} -if(data190.media_type !== undefined){ -if(typeof data190.media_type !== "string"){ -const err381 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -} -if(data190.source !== undefined){ -if(typeof data190.source !== "string"){ -const err382 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/error_details/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -} -} -} -if(data182.model_calls !== undefined){ -let data198 = data182.model_calls; -if(!((typeof data198 == "number") && (!(data198 % 1) && !isNaN(data198)))){ -const err383 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/model_calls",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -} -if(data182.compactions !== undefined){ -let data199 = data182.compactions; -if(!((typeof data199 == "number") && (!(data199 % 1) && !isNaN(data199)))){ -const err384 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/compactions",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -} -if(data182.last_activity_at !== undefined){ -if(typeof data182.last_activity_at !== "string"){ -const err385 = {instancePath:instancePath+"/items/" + i0+"/agent/last_turn/last_activity_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -} -} -} -if(data180.id !== undefined){ -if(typeof data180.id !== "string"){ -const err386 = {instancePath:instancePath+"/items/" + i0+"/agent/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -if(data180.root_id !== undefined){ -if(typeof data180.root_id !== "string"){ -const err387 = {instancePath:instancePath+"/items/" + i0+"/agent/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -} -if(data180.parent_id !== undefined){ -if(typeof data180.parent_id !== "string"){ -const err388 = {instancePath:instancePath+"/items/" + i0+"/agent/parent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err388]; -} -else { -vErrors.push(err388); -} -errors++; -} -} -if(data180.name !== undefined){ -if(typeof data180.name !== "string"){ -const err389 = {instancePath:instancePath+"/items/" + i0+"/agent/name",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err389]; -} -else { -vErrors.push(err389); -} -errors++; -} -} -if(data180.model !== undefined){ -if(typeof data180.model !== "string"){ -const err390 = {instancePath:instancePath+"/items/" + i0+"/agent/model",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err390]; -} -else { -vErrors.push(err390); -} -errors++; -} -} -if(data180.provider !== undefined){ -if(typeof data180.provider !== "string"){ -const err391 = {instancePath:instancePath+"/items/" + i0+"/agent/provider",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err391]; -} -else { -vErrors.push(err391); -} -errors++; -} -} -if(data180.effort !== undefined){ -if(typeof data180.effort !== "string"){ -const err392 = {instancePath:instancePath+"/items/" + i0+"/agent/effort",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err392]; -} -else { -vErrors.push(err392); -} -errors++; -} -} -if(data180.cwd !== undefined){ -if(typeof data180.cwd !== "string"){ -const err393 = {instancePath:instancePath+"/items/" + i0+"/agent/cwd",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err393]; -} -else { -vErrors.push(err393); -} -errors++; -} -} -if(data180.report !== undefined){ -if(typeof data180.report !== "string"){ -const err394 = {instancePath:instancePath+"/items/" + i0+"/agent/report",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err394]; -} -else { -vErrors.push(err394); -} -errors++; -} -} -if(data180.status !== undefined){ -if(typeof data180.status !== "string"){ -const err395 = {instancePath:instancePath+"/items/" + i0+"/agent/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err395]; -} -else { -vErrors.push(err395); -} -errors++; -} -} -if(data180.pending_mail !== undefined){ -let data211 = data180.pending_mail; -if(!((typeof data211 == "number") && (!(data211 % 1) && !isNaN(data211)))){ -const err396 = {instancePath:instancePath+"/items/" + i0+"/agent/pending_mail",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err396]; -} -else { -vErrors.push(err396); -} -errors++; -} -} -if(data180.lifecycle_phase !== undefined){ -if(typeof data180.lifecycle_phase !== "string"){ -const err397 = {instancePath:instancePath+"/items/" + i0+"/agent/lifecycle_phase",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err397]; -} -else { -vErrors.push(err397); -} -errors++; -} -} -if(data180.blocking_reason !== undefined){ -if(typeof data180.blocking_reason !== "string"){ -const err398 = {instancePath:instancePath+"/items/" + i0+"/agent/blocking_reason",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err398]; -} -else { -vErrors.push(err398); -} -errors++; -} -} -if(data180.terminal_cause !== undefined){ -if(typeof data180.terminal_cause !== "string"){ -const err399 = {instancePath:instancePath+"/items/" + i0+"/agent/terminal_cause",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err399]; -} -else { -vErrors.push(err399); -} -errors++; -} -} -if(data180.allowed_controls !== undefined){ -let data215 = data180.allowed_controls; -if((data215 !== null) && (!(Array.isArray(data215)))){ -const err400 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls",schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/allowed_controls/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[0].properties.agent.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err400]; -} -else { -vErrors.push(err400); -} -errors++; -} -if(Array.isArray(data215)){ -const len9 = data215.length; -for(let i9=0; i9<len9; i9++){ -if(typeof data215[i9] !== "string"){ -const err401 = {instancePath:instancePath+"/items/" + i0+"/agent/allowed_controls/" + i9,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/properties/agent/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err401]; -} -else { -vErrors.push(err401); -} -errors++; -} -} -} -} -} -} -} -else { -const err402 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/0/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err402]; -} -else { -vErrors.push(err402); -} -errors++; -} -var _valid0 = _errs387 === errors; -if(_valid0){ -valid42 = true; -passing0 = 0; -} -const _errs467 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.inbox === undefined){ -const err403 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/required",keyword:"required",params:{missingProperty: "inbox"},message:"must have required property '"+"inbox"+"'"}; -if(vErrors === null){ -vErrors = [err403]; -} -else { -vErrors.push(err403); -} -errors++; -} -if(data5.inbox !== undefined){ -let data217 = data5.inbox; -if((data217 !== null) && (!(data217 && typeof data217 == "object" && !Array.isArray(data217)))){ -const err404 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err404]; -} -else { -vErrors.push(err404); -} -errors++; -} -if(data217 && typeof data217 == "object" && !Array.isArray(data217)){ -if(data217.root_id === undefined){ -const err405 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err405]; -} -else { -vErrors.push(err405); -} -errors++; -} -if(data217.agent_id === undefined){ -const err406 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err406]; -} -else { -vErrors.push(err406); -} -errors++; -} -if(data217.seq === undefined){ -const err407 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err407]; -} -else { -vErrors.push(err407); -} -errors++; -} -if(data217.kind === undefined){ -const err408 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err408]; -} -else { -vErrors.push(err408); -} -errors++; -} -if(data217.status === undefined){ -const err409 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err409]; -} -else { -vErrors.push(err409); -} -errors++; -} -if(data217.payload === undefined){ -const err410 = {instancePath:instancePath+"/items/" + i0+"/inbox",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err410]; -} -else { -vErrors.push(err410); -} -errors++; -} -if(data217.delivery_seq !== undefined){ -let data218 = data217.delivery_seq; -if(typeof data218 === "string"){ -if(!pattern0.test(data218)){ -const err411 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err411]; -} -else { -vErrors.push(err411); -} -errors++; -} -if(!(formats0.validate(data218))){ -const err412 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err412]; -} -else { -vErrors.push(err412); -} -errors++; -} -} -else { -const err413 = {instancePath:instancePath+"/items/" + i0+"/inbox/delivery_seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err413]; -} -else { -vErrors.push(err413); -} -errors++; -} -} -if(data217.origin !== undefined){ -if(typeof data217.origin !== "string"){ -const err414 = {instancePath:instancePath+"/items/" + i0+"/inbox/origin",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err414]; -} -else { -vErrors.push(err414); -} -errors++; -} -} -if(data217.command_client_id !== undefined){ -if(typeof data217.command_client_id !== "string"){ -const err415 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_client_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err415]; -} -else { -vErrors.push(err415); -} -errors++; -} -} -if(data217.command_id !== undefined){ -if(typeof data217.command_id !== "string"){ -const err416 = {instancePath:instancePath+"/items/" + i0+"/inbox/command_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err416]; -} -else { -vErrors.push(err416); -} -errors++; -} -} -if(data217.steer_turn_id !== undefined){ -if(typeof data217.steer_turn_id !== "string"){ -const err417 = {instancePath:instancePath+"/items/" + i0+"/inbox/steer_turn_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err417]; -} -else { -vErrors.push(err417); -} -errors++; -} -} -if(data217.preview !== undefined){ -let data223 = data217.preview; -if((data223 !== null) && (!(data223 && typeof data223 == "object" && !Array.isArray(data223)))){ -const err418 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err418]; -} -else { -vErrors.push(err418); -} -errors++; -} -if(data223 && typeof data223 == "object" && !Array.isArray(data223)){ -if(data223.text === undefined){ -const err419 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err419]; -} -else { -vErrors.push(err419); -} -errors++; -} -if(data223.design_context !== undefined){ -let data224 = data223.design_context; -if((data224 !== null) && (!(data224 && typeof data224 == "object" && !Array.isArray(data224)))){ -const err420 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err420]; -} -else { -vErrors.push(err420); -} -errors++; -} -if(data224 && typeof data224 == "object" && !Array.isArray(data224)){ -if(data224.context_attachment_id === undefined){ -const err421 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err421]; -} -else { -vErrors.push(err421); -} -errors++; -} -if(data224.elements === undefined){ -const err422 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err422]; -} -else { -vErrors.push(err422); -} -errors++; -} -if(data224.element_count === undefined){ -const err423 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err423]; -} -else { -vErrors.push(err423); -} -errors++; -} -if(data224.context_attachment_id !== undefined){ -if(typeof data224.context_attachment_id !== "string"){ -const err424 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/context_attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err424]; -} -else { -vErrors.push(err424); -} -errors++; -} -} -if(data224.screenshot_attachment_id !== undefined){ -if(typeof data224.screenshot_attachment_id !== "string"){ -const err425 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err425]; -} -else { -vErrors.push(err425); -} -errors++; -} -} -if(data224.elements !== undefined){ -let data227 = data224.elements; -if((data227 !== null) && (!(Array.isArray(data227)))){ -const err426 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err426]; -} -else { -vErrors.push(err426); -} -errors++; -} -if(Array.isArray(data227)){ -const len10 = data227.length; -for(let i10=0; i10<len10; i10++){ -let data228 = data227[i10]; -if(data228 && typeof data228 == "object" && !Array.isArray(data228)){ -if(data228.label === undefined){ -const err427 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err427]; -} -else { -vErrors.push(err427); -} -errors++; -} -if(data228.label !== undefined){ -if(typeof data228.label !== "string"){ -const err428 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10+"/label",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err428]; -} -else { -vErrors.push(err428); -} -errors++; -} -} -if(data228.selector !== undefined){ -if(typeof data228.selector !== "string"){ -const err429 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10+"/selector",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err429]; -} -else { -vErrors.push(err429); -} -errors++; -} -} -} -else { -const err430 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/elements/" + i10,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err430]; -} -else { -vErrors.push(err430); -} -errors++; -} -} -} -} -if(data224.element_count !== undefined){ -let data231 = data224.element_count; -if(!((typeof data231 == "number") && (!(data231 % 1) && !isNaN(data231)))){ -const err431 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/element_count",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err431]; -} -else { -vErrors.push(err431); -} -errors++; -} -} -if(data224.page_url !== undefined){ -if(typeof data224.page_url !== "string"){ -const err432 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_url",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err432]; -} -else { -vErrors.push(err432); -} -errors++; -} -} -if(data224.page_title !== undefined){ -if(typeof data224.page_title !== "string"){ -const err433 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/design_context/page_title",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err433]; -} -else { -vErrors.push(err433); -} -errors++; -} -} -} -} -if(data223.text !== undefined){ -if(typeof data223.text !== "string"){ -const err434 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err434]; -} -else { -vErrors.push(err434); -} -errors++; -} -} -if(data223.truncated !== undefined){ -if(typeof data223.truncated !== "boolean"){ -const err435 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/truncated",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err435]; -} -else { -vErrors.push(err435); -} -errors++; -} -} -if(data223.attachments !== undefined){ -let data236 = data223.attachments; -if((data236 !== null) && (!(Array.isArray(data236)))){ -const err436 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err436]; -} -else { -vErrors.push(err436); -} -errors++; -} -if(Array.isArray(data236)){ -const len11 = data236.length; -for(let i11=0; i11<len11; i11++){ -let data237 = data236[i11]; -if(data237 && typeof data237 == "object" && !Array.isArray(data237)){ -if(data237.kind === undefined){ -const err437 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err437]; -} -else { -vErrors.push(err437); -} -errors++; -} -if(data237.content === undefined){ -const err438 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err438]; -} -else { -vErrors.push(err438); -} -errors++; -} -if(data237.kind !== undefined){ -if(typeof data237.kind !== "string"){ -const err439 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err439]; -} -else { -vErrors.push(err439); -} -errors++; -} -} -if(data237.name !== undefined){ -if(typeof data237.name !== "string"){ -const err440 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/name",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err440]; -} -else { -vErrors.push(err440); -} -errors++; -} -} -if(data237.content !== undefined){ -let data240 = data237.content; -if(data240 && typeof data240 == "object" && !Array.isArray(data240)){ -if(data240.reference_id === undefined){ -const err441 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err441]; -} -else { -vErrors.push(err441); -} -errors++; -} -if(data240.digest === undefined){ -const err442 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err442]; -} -else { -vErrors.push(err442); -} -errors++; -} -if(data240.size === undefined){ -const err443 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err443]; -} -else { -vErrors.push(err443); -} -errors++; -} -if(data240.media_type === undefined){ -const err444 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err444]; -} -else { -vErrors.push(err444); -} -errors++; -} -if(data240.source === undefined){ -const err445 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err445]; -} -else { -vErrors.push(err445); -} -errors++; -} -if(data240.text !== undefined){ -let data241 = data240.text; -if((data241 !== null) && (typeof data241 !== "string")){ -const err446 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err446]; -} -else { -vErrors.push(err446); -} -errors++; -} -} -if(data240.binary !== undefined){ -let data242 = data240.binary; -if((typeof data242 !== "string") && (data242 !== null)){ -const err447 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err447]; -} -else { -vErrors.push(err447); -} -errors++; -} -} -if(data240.reference_id !== undefined){ -if(typeof data240.reference_id !== "string"){ -const err448 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err448]; -} -else { -vErrors.push(err448); -} -errors++; -} -} -if(data240.digest !== undefined){ -if(typeof data240.digest !== "string"){ -const err449 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err449]; -} -else { -vErrors.push(err449); -} -errors++; -} -} -if(data240.size !== undefined){ -let data245 = data240.size; -if(typeof data245 === "string"){ -if(!pattern0.test(data245)){ -const err450 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err450]; -} -else { -vErrors.push(err450); -} -errors++; -} -if(!(formats0.validate(data245))){ -const err451 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err451]; -} -else { -vErrors.push(err451); -} -errors++; -} -} -else { -const err452 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err452]; -} -else { -vErrors.push(err452); -} -errors++; -} -} -if(data240.media_type !== undefined){ -if(typeof data240.media_type !== "string"){ -const err453 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err453]; -} -else { -vErrors.push(err453); -} -errors++; -} -} -if(data240.source !== undefined){ -if(typeof data240.source !== "string"){ -const err454 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err454]; -} -else { -vErrors.push(err454); -} -errors++; -} -} -} -else { -const err455 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11+"/content",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err455]; -} -else { -vErrors.push(err455); -} -errors++; -} -} -} -else { -const err456 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachments/" + i11,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err456]; -} -else { -vErrors.push(err456); -} -errors++; -} -} -} -} -if(data223.attachment_count !== undefined){ -let data248 = data223.attachment_count; -if(!((typeof data248 == "number") && (!(data248 % 1) && !isNaN(data248)))){ -const err457 = {instancePath:instancePath+"/items/" + i0+"/inbox/preview/attachment_count",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err457]; -} -else { -vErrors.push(err457); -} -errors++; -} -} -} -} -if(data217.root_id !== undefined){ -if(typeof data217.root_id !== "string"){ -const err458 = {instancePath:instancePath+"/items/" + i0+"/inbox/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err458]; -} -else { -vErrors.push(err458); -} -errors++; -} -} -if(data217.agent_id !== undefined){ -if(typeof data217.agent_id !== "string"){ -const err459 = {instancePath:instancePath+"/items/" + i0+"/inbox/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err459]; -} -else { -vErrors.push(err459); -} -errors++; -} -} -if(data217.seq !== undefined){ -let data251 = data217.seq; -if(typeof data251 === "string"){ -if(!pattern0.test(data251)){ -const err460 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err460]; -} -else { -vErrors.push(err460); -} -errors++; -} -if(!(formats0.validate(data251))){ -const err461 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err461]; -} -else { -vErrors.push(err461); -} -errors++; -} -} -else { -const err462 = {instancePath:instancePath+"/items/" + i0+"/inbox/seq",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err462]; -} -else { -vErrors.push(err462); -} -errors++; -} -} -if(data217.kind !== undefined){ -if(typeof data217.kind !== "string"){ -const err463 = {instancePath:instancePath+"/items/" + i0+"/inbox/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err463]; -} -else { -vErrors.push(err463); -} -errors++; -} -} -if(data217.status !== undefined){ -if(typeof data217.status !== "string"){ -const err464 = {instancePath:instancePath+"/items/" + i0+"/inbox/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err464]; -} -else { -vErrors.push(err464); -} -errors++; -} -} -if(data217.payload !== undefined){ -let data254 = data217.payload; -if(data254 && typeof data254 == "object" && !Array.isArray(data254)){ -if(data254.reference_id === undefined){ -const err465 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err465]; -} -else { -vErrors.push(err465); -} -errors++; -} -if(data254.digest === undefined){ -const err466 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err466]; -} -else { -vErrors.push(err466); -} -errors++; -} -if(data254.size === undefined){ -const err467 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err467]; -} -else { -vErrors.push(err467); -} -errors++; -} -if(data254.media_type === undefined){ -const err468 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err468]; -} -else { -vErrors.push(err468); -} -errors++; -} -if(data254.source === undefined){ -const err469 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err469]; -} -else { -vErrors.push(err469); -} -errors++; -} -if(data254.text !== undefined){ -let data255 = data254.text; -if((data255 !== null) && (typeof data255 !== "string")){ -const err470 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err470]; -} -else { -vErrors.push(err470); -} -errors++; -} -} -if(data254.binary !== undefined){ -let data256 = data254.binary; -if((typeof data256 !== "string") && (data256 !== null)){ -const err471 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[1].properties.inbox.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err471]; -} -else { -vErrors.push(err471); -} -errors++; -} -} -if(data254.reference_id !== undefined){ -if(typeof data254.reference_id !== "string"){ -const err472 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err472]; -} -else { -vErrors.push(err472); -} -errors++; -} -} -if(data254.digest !== undefined){ -if(typeof data254.digest !== "string"){ -const err473 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err473]; -} -else { -vErrors.push(err473); -} -errors++; -} -} -if(data254.size !== undefined){ -let data259 = data254.size; -if(typeof data259 === "string"){ -if(!pattern0.test(data259)){ -const err474 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err474]; -} -else { -vErrors.push(err474); -} -errors++; -} -if(!(formats0.validate(data259))){ -const err475 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err475]; -} -else { -vErrors.push(err475); -} -errors++; -} -} -else { -const err476 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err476]; -} -else { -vErrors.push(err476); -} -errors++; -} -} -if(data254.media_type !== undefined){ -if(typeof data254.media_type !== "string"){ -const err477 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err477]; -} -else { -vErrors.push(err477); -} -errors++; -} -} -if(data254.source !== undefined){ -if(typeof data254.source !== "string"){ -const err478 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err478]; -} -else { -vErrors.push(err478); -} -errors++; -} -} -} -else { -const err479 = {instancePath:instancePath+"/items/" + i0+"/inbox/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/1/properties/inbox/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err479]; -} -else { -vErrors.push(err479); -} -errors++; -} -} -} -} -} -else { -const err480 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/1/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err480]; -} -else { -vErrors.push(err480); -} -errors++; -} -var _valid0 = _errs467 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 1]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 1; -} -const _errs567 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.blackboard === undefined){ -const err481 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/2/required",keyword:"required",params:{missingProperty: "blackboard"},message:"must have required property '"+"blackboard"+"'"}; -if(vErrors === null){ -vErrors = [err481]; -} -else { -vErrors.push(err481); -} -errors++; -} -if(data5.blackboard !== undefined){ -let data262 = data5.blackboard; -if((data262 !== null) && (!(data262 && typeof data262 == "object" && !Array.isArray(data262)))){ -const err482 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err482]; -} -else { -vErrors.push(err482); -} -errors++; -} -if(data262 && typeof data262 == "object" && !Array.isArray(data262)){ -if(data262.key === undefined){ -const err483 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err483]; -} -else { -vErrors.push(err483); -} -errors++; -} -if(data262.version === undefined){ -const err484 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err484]; -} -else { -vErrors.push(err484); -} -errors++; -} -if(data262.author_agent_id === undefined){ -const err485 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err485]; -} -else { -vErrors.push(err485); -} -errors++; -} -if(data262.payload === undefined){ -const err486 = {instancePath:instancePath+"/items/" + i0+"/blackboard",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err486]; -} -else { -vErrors.push(err486); -} -errors++; -} -if(data262.key !== undefined){ -if(typeof data262.key !== "string"){ -const err487 = {instancePath:instancePath+"/items/" + i0+"/blackboard/key",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err487]; -} -else { -vErrors.push(err487); -} -errors++; -} -} -if(data262.version !== undefined){ -let data264 = data262.version; -if(typeof data264 === "string"){ -if(!pattern0.test(data264)){ -const err488 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err488]; -} -else { -vErrors.push(err488); -} -errors++; -} -if(!(formats0.validate(data264))){ -const err489 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err489]; -} -else { -vErrors.push(err489); -} -errors++; -} -} -else { -const err490 = {instancePath:instancePath+"/items/" + i0+"/blackboard/version",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err490]; -} -else { -vErrors.push(err490); -} -errors++; -} -} -if(data262.author_agent_id !== undefined){ -if(typeof data262.author_agent_id !== "string"){ -const err491 = {instancePath:instancePath+"/items/" + i0+"/blackboard/author_agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err491]; -} -else { -vErrors.push(err491); -} -errors++; -} -} -if(data262.payload !== undefined){ -let data266 = data262.payload; -if(data266 && typeof data266 == "object" && !Array.isArray(data266)){ -if(data266.reference_id === undefined){ -const err492 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err492]; -} -else { -vErrors.push(err492); -} -errors++; -} -if(data266.digest === undefined){ -const err493 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err493]; -} -else { -vErrors.push(err493); -} -errors++; -} -if(data266.size === undefined){ -const err494 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err494]; -} -else { -vErrors.push(err494); -} -errors++; -} -if(data266.media_type === undefined){ -const err495 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err495]; -} -else { -vErrors.push(err495); -} -errors++; -} -if(data266.source === undefined){ -const err496 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err496]; -} -else { -vErrors.push(err496); -} -errors++; -} -if(data266.text !== undefined){ -let data267 = data266.text; -if((data267 !== null) && (typeof data267 !== "string")){ -const err497 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err497]; -} -else { -vErrors.push(err497); -} -errors++; -} -} -if(data266.binary !== undefined){ -let data268 = data266.binary; -if((typeof data268 !== "string") && (data268 !== null)){ -const err498 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[2].properties.blackboard.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err498]; -} -else { -vErrors.push(err498); -} -errors++; -} -} -if(data266.reference_id !== undefined){ -if(typeof data266.reference_id !== "string"){ -const err499 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err499]; -} -else { -vErrors.push(err499); -} -errors++; -} -} -if(data266.digest !== undefined){ -if(typeof data266.digest !== "string"){ -const err500 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err500]; -} -else { -vErrors.push(err500); -} -errors++; -} -} -if(data266.size !== undefined){ -let data271 = data266.size; -if(typeof data271 === "string"){ -if(!pattern0.test(data271)){ -const err501 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err501]; -} -else { -vErrors.push(err501); -} -errors++; -} -if(!(formats0.validate(data271))){ -const err502 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err502]; -} -else { -vErrors.push(err502); -} -errors++; -} -} -else { -const err503 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err503]; -} -else { -vErrors.push(err503); -} -errors++; -} -} -if(data266.media_type !== undefined){ -if(typeof data266.media_type !== "string"){ -const err504 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err504]; -} -else { -vErrors.push(err504); -} -errors++; -} -} -if(data266.source !== undefined){ -if(typeof data266.source !== "string"){ -const err505 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err505]; -} -else { -vErrors.push(err505); -} -errors++; -} -} -} -else { -const err506 = {instancePath:instancePath+"/items/" + i0+"/blackboard/payload",schemaPath:"#/properties/items/items/allOf/1/oneOf/2/properties/blackboard/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err506]; -} -else { -vErrors.push(err506); -} -errors++; -} -} -} -} -} -else { -const err507 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/2/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err507]; -} -else { -vErrors.push(err507); -} -errors++; -} -var _valid0 = _errs567 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 2]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 2; -} -const _errs596 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.budget === undefined){ -const err508 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/3/required",keyword:"required",params:{missingProperty: "budget"},message:"must have required property '"+"budget"+"'"}; -if(vErrors === null){ -vErrors = [err508]; -} -else { -vErrors.push(err508); -} -errors++; -} -if(data5.budget !== undefined){ -let data274 = data5.budget; -if((data274 !== null) && (!(data274 && typeof data274 == "object" && !Array.isArray(data274)))){ -const err509 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err509]; -} -else { -vErrors.push(err509); -} -errors++; -} -if(data274 && typeof data274 == "object" && !Array.isArray(data274)){ -if(data274.agent_id === undefined){ -const err510 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err510]; -} -else { -vErrors.push(err510); -} -errors++; -} -if(data274.state === undefined){ -const err511 = {instancePath:instancePath+"/items/" + i0+"/budget",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err511]; -} -else { -vErrors.push(err511); -} -errors++; -} -if(data274.agent_id !== undefined){ -if(typeof data274.agent_id !== "string"){ -const err512 = {instancePath:instancePath+"/items/" + i0+"/budget/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err512]; -} -else { -vErrors.push(err512); -} -errors++; -} -} -if(data274.state !== undefined){ -let data276 = data274.state; -if(data276 && typeof data276 == "object" && !Array.isArray(data276)){ -if(data276.kind === undefined){ -const err513 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err513]; -} -else { -vErrors.push(err513); -} -errors++; -} -if(data276.limit === undefined){ -const err514 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err514]; -} -else { -vErrors.push(err514); -} -errors++; -} -if(data276.used === undefined){ -const err515 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err515]; -} -else { -vErrors.push(err515); -} -errors++; -} -if(data276.reserved === undefined){ -const err516 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err516]; -} -else { -vErrors.push(err516); -} -errors++; -} -if(data276.remaining === undefined){ -const err517 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err517]; -} -else { -vErrors.push(err517); -} -errors++; -} -if(data276.uncertain === undefined){ -const err518 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err518]; -} -else { -vErrors.push(err518); -} -errors++; -} -if(data276.incomplete === undefined){ -const err519 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err519]; -} -else { -vErrors.push(err519); -} -errors++; -} -if(data276.kind !== undefined){ -if(typeof data276.kind !== "string"){ -const err520 = {instancePath:instancePath+"/items/" + i0+"/budget/state/kind",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err520]; -} -else { -vErrors.push(err520); -} -errors++; -} -} -if(data276.limit !== undefined){ -let data278 = data276.limit; -if((typeof data278 !== "string") && (data278 !== null)){ -const err521 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err521]; -} -else { -vErrors.push(err521); -} -errors++; -} -if(typeof data278 === "string"){ -if(!pattern0.test(data278)){ -const err522 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err522]; -} -else { -vErrors.push(err522); -} -errors++; -} -if(!(formats0.validate(data278))){ -const err523 = {instancePath:instancePath+"/items/" + i0+"/budget/state/limit",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err523]; -} -else { -vErrors.push(err523); -} -errors++; -} -} -} -if(data276.used !== undefined){ -let data279 = data276.used; -if(typeof data279 === "string"){ -if(!pattern0.test(data279)){ -const err524 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err524]; -} -else { -vErrors.push(err524); -} -errors++; -} -if(!(formats0.validate(data279))){ -const err525 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err525]; -} -else { -vErrors.push(err525); -} -errors++; -} -} -else { -const err526 = {instancePath:instancePath+"/items/" + i0+"/budget/state/used",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err526]; -} -else { -vErrors.push(err526); -} -errors++; -} -} -if(data276.reserved !== undefined){ -let data280 = data276.reserved; -if(typeof data280 === "string"){ -if(!pattern0.test(data280)){ -const err527 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err527]; -} -else { -vErrors.push(err527); -} -errors++; -} -if(!(formats0.validate(data280))){ -const err528 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err528]; -} -else { -vErrors.push(err528); -} -errors++; -} -} -else { -const err529 = {instancePath:instancePath+"/items/" + i0+"/budget/state/reserved",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err529]; -} -else { -vErrors.push(err529); -} -errors++; -} -} -if(data276.remaining !== undefined){ -let data281 = data276.remaining; -if((typeof data281 !== "string") && (data281 !== null)){ -const err530 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[3].properties.budget.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err530]; -} -else { -vErrors.push(err530); -} -errors++; -} -if(typeof data281 === "string"){ -if(!pattern0.test(data281)){ -const err531 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err531]; -} -else { -vErrors.push(err531); -} -errors++; -} -if(!(formats0.validate(data281))){ -const err532 = {instancePath:instancePath+"/items/" + i0+"/budget/state/remaining",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err532]; -} -else { -vErrors.push(err532); -} -errors++; -} -} -} -if(data276.uncertain !== undefined){ -let data282 = data276.uncertain; -if(typeof data282 === "string"){ -if(!pattern0.test(data282)){ -const err533 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err533]; -} -else { -vErrors.push(err533); -} -errors++; -} -if(!(formats0.validate(data282))){ -const err534 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err534]; -} -else { -vErrors.push(err534); -} -errors++; -} -} -else { -const err535 = {instancePath:instancePath+"/items/" + i0+"/budget/state/uncertain",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err535]; -} -else { -vErrors.push(err535); -} -errors++; -} -} -if(data276.incomplete !== undefined){ -if(typeof data276.incomplete !== "boolean"){ -const err536 = {instancePath:instancePath+"/items/" + i0+"/budget/state/incomplete",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err536]; -} -else { -vErrors.push(err536); -} -errors++; -} -} -} -else { -const err537 = {instancePath:instancePath+"/items/" + i0+"/budget/state",schemaPath:"#/properties/items/items/allOf/1/oneOf/3/properties/budget/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err537]; -} -else { -vErrors.push(err537); -} -errors++; -} -} -} -} -} -else { -const err538 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/3/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err538]; -} -else { -vErrors.push(err538); -} -errors++; -} -var _valid0 = _errs596 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 3]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 3; -} -const _errs621 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.capability === undefined){ -const err539 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/required",keyword:"required",params:{missingProperty: "capability"},message:"must have required property '"+"capability"+"'"}; -if(vErrors === null){ -vErrors = [err539]; -} -else { -vErrors.push(err539); -} -errors++; -} -if(data5.capability !== undefined){ -let data284 = data5.capability; -if((data284 !== null) && (!(data284 && typeof data284 == "object" && !Array.isArray(data284)))){ -const err540 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err540]; -} -else { -vErrors.push(err540); -} -errors++; -} -if(data284 && typeof data284 == "object" && !Array.isArray(data284)){ -if(data284.id === undefined){ -const err541 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err541]; -} -else { -vErrors.push(err541); -} -errors++; -} -if(data284.root_id === undefined){ -const err542 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err542]; -} -else { -vErrors.push(err542); -} -errors++; -} -if(data284.agent_id === undefined){ -const err543 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err543]; -} -else { -vErrors.push(err543); -} -errors++; -} -if(data284.issuer_agent_id === undefined){ -const err544 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err544]; -} -else { -vErrors.push(err544); -} -errors++; -} -if(data284.operations === undefined){ -const err545 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err545]; -} -else { -vErrors.push(err545); -} -errors++; -} -if(data284.scopes === undefined){ -const err546 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err546]; -} -else { -vErrors.push(err546); -} -errors++; -} -if(data284.mcp === undefined){ -const err547 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err547]; -} -else { -vErrors.push(err547); -} -errors++; -} -if(data284.mcp_all === undefined){ -const err548 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err548]; -} -else { -vErrors.push(err548); -} -errors++; -} -if(data284.generation === undefined){ -const err549 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err549]; -} -else { -vErrors.push(err549); -} -errors++; -} -if(data284.status === undefined){ -const err550 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err550]; -} -else { -vErrors.push(err550); -} -errors++; -} -if(data284.expires_at === undefined){ -const err551 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err551]; -} -else { -vErrors.push(err551); -} -errors++; -} -if(data284.created_at === undefined){ -const err552 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err552]; -} -else { -vErrors.push(err552); -} -errors++; -} -if(data284.updated_at === undefined){ -const err553 = {instancePath:instancePath+"/items/" + i0+"/capability",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err553]; -} -else { -vErrors.push(err553); -} -errors++; -} -if(data284.id !== undefined){ -if(typeof data284.id !== "string"){ -const err554 = {instancePath:instancePath+"/items/" + i0+"/capability/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err554]; -} -else { -vErrors.push(err554); -} -errors++; -} -} -if(data284.root_id !== undefined){ -if(typeof data284.root_id !== "string"){ -const err555 = {instancePath:instancePath+"/items/" + i0+"/capability/root_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err555]; -} -else { -vErrors.push(err555); -} -errors++; -} -} -if(data284.agent_id !== undefined){ -if(typeof data284.agent_id !== "string"){ -const err556 = {instancePath:instancePath+"/items/" + i0+"/capability/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err556]; -} -else { -vErrors.push(err556); -} -errors++; -} -} -if(data284.issuer_agent_id !== undefined){ -if(typeof data284.issuer_agent_id !== "string"){ -const err557 = {instancePath:instancePath+"/items/" + i0+"/capability/issuer_agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err557]; -} -else { -vErrors.push(err557); -} -errors++; -} -} -if(data284.operations !== undefined){ -let data289 = data284.operations; -if((data289 !== null) && (!(Array.isArray(data289)))){ -const err558 = {instancePath:instancePath+"/items/" + i0+"/capability/operations",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/operations/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err558]; -} -else { -vErrors.push(err558); -} -errors++; -} -if(Array.isArray(data289)){ -const len12 = data289.length; -for(let i12=0; i12<len12; i12++){ -if(typeof data289[i12] !== "string"){ -const err559 = {instancePath:instancePath+"/items/" + i0+"/capability/operations/" + i12,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err559]; -} -else { -vErrors.push(err559); -} -errors++; -} -} -} -} -if(data284.scopes !== undefined){ -let data291 = data284.scopes; -if((data291 !== null) && (!(Array.isArray(data291)))){ -const err560 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/scopes/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err560]; -} -else { -vErrors.push(err560); -} -errors++; -} -if(Array.isArray(data291)){ -const len13 = data291.length; -for(let i13=0; i13<len13; i13++){ -if(typeof data291[i13] !== "string"){ -const err561 = {instancePath:instancePath+"/items/" + i0+"/capability/scopes/" + i13,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err561]; -} -else { -vErrors.push(err561); -} -errors++; -} -} -} -} -if(data284.file_scope !== undefined){ -if(typeof data284.file_scope !== "string"){ -const err562 = {instancePath:instancePath+"/items/" + i0+"/capability/file_scope",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err562]; -} -else { -vErrors.push(err562); -} -errors++; -} -} -if(data284.file_issuer_id !== undefined){ -if(typeof data284.file_issuer_id !== "string"){ -const err563 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err563]; -} -else { -vErrors.push(err563); -} -errors++; -} -} -if(data284.file_issuer_generation !== undefined){ -let data295 = data284.file_issuer_generation; -if(typeof data295 === "string"){ -if(!pattern0.test(data295)){ -const err564 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err564]; -} -else { -vErrors.push(err564); -} -errors++; -} -if(!(formats0.validate(data295))){ -const err565 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err565]; -} -else { -vErrors.push(err565); -} -errors++; -} -} -else { -const err566 = {instancePath:instancePath+"/items/" + i0+"/capability/file_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err566]; -} -else { -vErrors.push(err566); -} -errors++; -} -} -if(data284.mcp !== undefined){ -let data296 = data284.mcp; -if((data296 !== null) && (!(Array.isArray(data296)))){ -const err567 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err567]; -} -else { -vErrors.push(err567); -} -errors++; -} -if(Array.isArray(data296)){ -const len14 = data296.length; -for(let i14=0; i14<len14; i14++){ -let data297 = data296[i14]; -if(data297 && typeof data297 == "object" && !Array.isArray(data297)){ -if(data297.server === undefined){ -const err568 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err568]; -} -else { -vErrors.push(err568); -} -errors++; -} -if(data297.tool === undefined){ -const err569 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err569]; -} -else { -vErrors.push(err569); -} -errors++; -} -if(data297.definition === undefined){ -const err570 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err570]; -} -else { -vErrors.push(err570); -} -errors++; -} -if(data297.server !== undefined){ -if(typeof data297.server !== "string"){ -const err571 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/server",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err571]; -} -else { -vErrors.push(err571); -} -errors++; -} -} -if(data297.tool !== undefined){ -if(typeof data297.tool !== "string"){ -const err572 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/tool",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err572]; -} -else { -vErrors.push(err572); -} -errors++; -} -} -if(data297.definition !== undefined){ -if(typeof data297.definition !== "string"){ -const err573 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14+"/definition",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err573]; -} -else { -vErrors.push(err573); -} -errors++; -} -} -} -else { -const err574 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp/" + i14,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err574]; -} -else { -vErrors.push(err574); -} -errors++; -} -} -} -} -if(data284.mcp_all !== undefined){ -if(typeof data284.mcp_all !== "boolean"){ -const err575 = {instancePath:instancePath+"/items/" + i0+"/capability/mcp_all",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err575]; -} -else { -vErrors.push(err575); -} -errors++; -} -} -if(data284.browser !== undefined){ -let data302 = data284.browser; -if((data302 !== null) && (!(data302 && typeof data302 == "object" && !Array.isArray(data302)))){ -const err576 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err576]; -} -else { -vErrors.push(err576); -} -errors++; -} -if(data302 && typeof data302 == "object" && !Array.isArray(data302)){ -if(data302.provider_id === undefined){ -const err577 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err577]; -} -else { -vErrors.push(err577); -} -errors++; -} -if(data302.provider_epoch === undefined){ -const err578 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err578]; -} -else { -vErrors.push(err578); -} -errors++; -} -if(data302.tab_id === undefined){ -const err579 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err579]; -} -else { -vErrors.push(err579); -} -errors++; -} -if(data302.tab_generation === undefined){ -const err580 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err580]; -} -else { -vErrors.push(err580); -} -errors++; -} -if(data302.profile_id === undefined){ -const err581 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err581]; -} -else { -vErrors.push(err581); -} -errors++; -} -if(data302.rights === undefined){ -const err582 = {instancePath:instancePath+"/items/" + i0+"/capability/browser",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err582]; -} -else { -vErrors.push(err582); -} -errors++; -} -if(data302.provider_id !== undefined){ -if(typeof data302.provider_id !== "string"){ -const err583 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err583]; -} -else { -vErrors.push(err583); -} -errors++; -} -} -if(data302.provider_epoch !== undefined){ -if(typeof data302.provider_epoch !== "string"){ -const err584 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/provider_epoch",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err584]; -} -else { -vErrors.push(err584); -} -errors++; -} -} -if(data302.tab_id !== undefined){ -if(typeof data302.tab_id !== "string"){ -const err585 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err585]; -} -else { -vErrors.push(err585); -} -errors++; -} -} -if(data302.tab_generation !== undefined){ -if(typeof data302.tab_generation !== "string"){ -const err586 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/tab_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err586]; -} -else { -vErrors.push(err586); -} -errors++; -} -} -if(data302.profile_id !== undefined){ -if(typeof data302.profile_id !== "string"){ -const err587 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/profile_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err587]; -} -else { -vErrors.push(err587); -} -errors++; -} -} -if(data302.attachment_id !== undefined){ -if(typeof data302.attachment_id !== "string"){ -const err588 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err588]; -} -else { -vErrors.push(err588); -} -errors++; -} -} -if(data302.attachment_generation !== undefined){ -if(typeof data302.attachment_generation !== "string"){ -const err589 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/attachment_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err589]; -} -else { -vErrors.push(err589); -} -errors++; -} -} -if(data302.rights !== undefined){ -let data310 = data302.rights; -if((data310 !== null) && (!(Array.isArray(data310)))){ -const err590 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/rights/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err590]; -} -else { -vErrors.push(err590); -} -errors++; -} -if(Array.isArray(data310)){ -const len15 = data310.length; -for(let i15=0; i15<len15; i15++){ -if(typeof data310[i15] !== "string"){ -const err591 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/rights/" + i15,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err591]; -} -else { -vErrors.push(err591); -} -errors++; -} -} -} -} -if(data302.preview !== undefined){ -let data312 = data302.preview; -if((data312 !== null) && (!(data312 && typeof data312 == "object" && !Array.isArray(data312)))){ -const err592 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err592]; -} -else { -vErrors.push(err592); -} -errors++; -} -if(data312 && typeof data312 == "object" && !Array.isArray(data312)){ -if(data312.host_id === undefined){ -const err593 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err593]; -} -else { -vErrors.push(err593); -} -errors++; -} -if(data312.host_identity === undefined){ -const err594 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err594]; -} -else { -vErrors.push(err594); -} -errors++; -} -if(data312.connection_generation === undefined){ -const err595 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err595]; -} -else { -vErrors.push(err595); -} -errors++; -} -if(data312.environment_id === undefined){ -const err596 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err596]; -} -else { -vErrors.push(err596); -} -errors++; -} -if(data312.loopback === undefined){ -const err597 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err597]; -} -else { -vErrors.push(err597); -} -errors++; -} -if(data312.ports === undefined){ -const err598 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err598]; -} -else { -vErrors.push(err598); -} -errors++; -} -if(data312.host_id !== undefined){ -if(typeof data312.host_id !== "string"){ -const err599 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err599]; -} -else { -vErrors.push(err599); -} -errors++; -} -} -if(data312.host_identity !== undefined){ -if(typeof data312.host_identity !== "string"){ -const err600 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/host_identity",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err600]; -} -else { -vErrors.push(err600); -} -errors++; -} -} -if(data312.connection_generation !== undefined){ -if(typeof data312.connection_generation !== "string"){ -const err601 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/connection_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err601]; -} -else { -vErrors.push(err601); -} -errors++; -} -} -if(data312.environment_id !== undefined){ -if(typeof data312.environment_id !== "string"){ -const err602 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/environment_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err602]; -} -else { -vErrors.push(err602); -} -errors++; -} -} -if(data312.loopback !== undefined){ -if(typeof data312.loopback !== "string"){ -const err603 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/loopback",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err603]; -} -else { -vErrors.push(err603); -} -errors++; -} -} -if(data312.ports !== undefined){ -let data318 = data312.ports; -if((data318 !== null) && (!(Array.isArray(data318)))){ -const err604 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[4].properties.capability.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err604]; -} -else { -vErrors.push(err604); -} -errors++; -} -if(Array.isArray(data318)){ -const len16 = data318.length; -for(let i16=0; i16<len16; i16++){ -let data319 = data318[i16]; -if(!((typeof data319 == "number") && (!(data319 % 1) && !isNaN(data319)))){ -const err605 = {instancePath:instancePath+"/items/" + i0+"/capability/browser/preview/ports/" + i16,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err605]; -} -else { -vErrors.push(err605); -} -errors++; -} -} -} -} -} -} -} -} -if(data284.browser_issuer_id !== undefined){ -if(typeof data284.browser_issuer_id !== "string"){ -const err606 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err606]; -} -else { -vErrors.push(err606); -} -errors++; -} -} -if(data284.browser_issuer_generation !== undefined){ -let data321 = data284.browser_issuer_generation; -if(!((typeof data321 == "number") && (!(data321 % 1) && !isNaN(data321)))){ -const err607 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_issuer_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err607]; -} -else { -vErrors.push(err607); -} -errors++; -} -} -if(data284.browser_delegation_only !== undefined){ -if(typeof data284.browser_delegation_only !== "boolean"){ -const err608 = {instancePath:instancePath+"/items/" + i0+"/capability/browser_delegation_only",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err608]; -} -else { -vErrors.push(err608); -} -errors++; -} -} -if(data284.generation !== undefined){ -let data323 = data284.generation; -if(typeof data323 === "string"){ -if(!pattern0.test(data323)){ -const err609 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err609]; -} -else { -vErrors.push(err609); -} -errors++; -} -if(!(formats0.validate(data323))){ -const err610 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err610]; -} -else { -vErrors.push(err610); -} -errors++; -} -} -else { -const err611 = {instancePath:instancePath+"/items/" + i0+"/capability/generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err611]; -} -else { -vErrors.push(err611); -} -errors++; -} -} -if(data284.status !== undefined){ -if(typeof data284.status !== "string"){ -const err612 = {instancePath:instancePath+"/items/" + i0+"/capability/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err612]; -} -else { -vErrors.push(err612); -} -errors++; -} -} -if(data284.expires_at !== undefined){ -if(typeof data284.expires_at !== "string"){ -const err613 = {instancePath:instancePath+"/items/" + i0+"/capability/expires_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err613]; -} -else { -vErrors.push(err613); -} -errors++; -} -} -if(data284.created_at !== undefined){ -if(typeof data284.created_at !== "string"){ -const err614 = {instancePath:instancePath+"/items/" + i0+"/capability/created_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err614]; -} -else { -vErrors.push(err614); -} -errors++; -} -} -if(data284.updated_at !== undefined){ -if(typeof data284.updated_at !== "string"){ -const err615 = {instancePath:instancePath+"/items/" + i0+"/capability/updated_at",schemaPath:"#/properties/items/items/allOf/1/oneOf/4/properties/capability/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err615]; -} -else { -vErrors.push(err615); -} -errors++; -} -} -} -} -} -else { -const err616 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/4/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err616]; -} -else { -vErrors.push(err616); -} -errors++; -} -var _valid0 = _errs621 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 4]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 4; -} -const _errs716 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.schedule === undefined){ -const err617 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/5/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err617]; -} -else { -vErrors.push(err617); -} -errors++; -} -if(data5.schedule !== undefined){ -let data328 = data5.schedule; -if((data328 !== null) && (!(data328 && typeof data328 == "object" && !Array.isArray(data328)))){ -const err618 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[5].properties.schedule.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err618]; -} -else { -vErrors.push(err618); -} -errors++; -} -if(data328 && typeof data328 == "object" && !Array.isArray(data328)){ -if(data328.id === undefined){ -const err619 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err619]; -} -else { -vErrors.push(err619); -} -errors++; -} -if(data328.schedule === undefined){ -const err620 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err620]; -} -else { -vErrors.push(err620); -} -errors++; -} -if(data328.prompt === undefined){ -const err621 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err621]; -} -else { -vErrors.push(err621); -} -errors++; -} -if(data328.anchor === undefined){ -const err622 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err622]; -} -else { -vErrors.push(err622); -} -errors++; -} -if(data328.last_fire === undefined){ -const err623 = {instancePath:instancePath+"/items/" + i0+"/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err623]; -} -else { -vErrors.push(err623); -} -errors++; -} -if(data328.id !== undefined){ -let data329 = data328.id; -if(!((typeof data329 == "number") && (!(data329 % 1) && !isNaN(data329)))){ -const err624 = {instancePath:instancePath+"/items/" + i0+"/schedule/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err624]; -} -else { -vErrors.push(err624); -} -errors++; -} -} -if(data328.schedule !== undefined){ -if(typeof data328.schedule !== "string"){ -const err625 = {instancePath:instancePath+"/items/" + i0+"/schedule/schedule",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err625]; -} -else { -vErrors.push(err625); -} -errors++; -} -} -if(data328.prompt !== undefined){ -if(typeof data328.prompt !== "string"){ -const err626 = {instancePath:instancePath+"/items/" + i0+"/schedule/prompt",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err626]; -} -else { -vErrors.push(err626); -} -errors++; -} -} -if(data328.anchor !== undefined){ -if(typeof data328.anchor !== "string"){ -const err627 = {instancePath:instancePath+"/items/" + i0+"/schedule/anchor",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err627]; -} -else { -vErrors.push(err627); -} -errors++; -} -} -if(data328.last_fire !== undefined){ -if(typeof data328.last_fire !== "string"){ -const err628 = {instancePath:instancePath+"/items/" + i0+"/schedule/last_fire",schemaPath:"#/properties/items/items/allOf/1/oneOf/5/properties/schedule/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err628]; -} -else { -vErrors.push(err628); -} -errors++; -} -} -} -} -} -else { -const err629 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/5/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err629]; -} -else { -vErrors.push(err629); -} -errors++; -} -var _valid0 = _errs716 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 5]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 5; -} -const _errs732 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.permission === undefined){ -const err630 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/6/required",keyword:"required",params:{missingProperty: "permission"},message:"must have required property '"+"permission"+"'"}; -if(vErrors === null){ -vErrors = [err630]; -} -else { -vErrors.push(err630); -} -errors++; -} -if(data5.permission !== undefined){ -let data334 = data5.permission; -if((data334 !== null) && (!(data334 && typeof data334 == "object" && !Array.isArray(data334)))){ -const err631 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[6].properties.permission.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err631]; -} -else { -vErrors.push(err631); -} -errors++; -} -if(data334 && typeof data334 == "object" && !Array.isArray(data334)){ -if(data334.id === undefined){ -const err632 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err632]; -} -else { -vErrors.push(err632); -} -errors++; -} -if(data334.agent_id === undefined){ -const err633 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err633]; -} -else { -vErrors.push(err633); -} -errors++; -} -if(data334.operation_id === undefined){ -const err634 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err634]; -} -else { -vErrors.push(err634); -} -errors++; -} -if(data334.operation === undefined){ -const err635 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err635]; -} -else { -vErrors.push(err635); -} -errors++; -} -if(data334.canonical_path === undefined){ -const err636 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err636]; -} -else { -vErrors.push(err636); -} -errors++; -} -if(data334.request_digest === undefined){ -const err637 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err637]; -} -else { -vErrors.push(err637); -} -errors++; -} -if(data334.capability_id === undefined){ -const err638 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err638]; -} -else { -vErrors.push(err638); -} -errors++; -} -if(data334.capability_generation === undefined){ -const err639 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err639]; -} -else { -vErrors.push(err639); -} -errors++; -} -if(data334.status === undefined){ -const err640 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err640]; -} -else { -vErrors.push(err640); -} -errors++; -} -if(data334.command === undefined){ -const err641 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err641]; -} -else { -vErrors.push(err641); -} -errors++; -} -if(data334.rule === undefined){ -const err642 = {instancePath:instancePath+"/items/" + i0+"/permission",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err642]; -} -else { -vErrors.push(err642); -} -errors++; -} -if(data334.id !== undefined){ -if(typeof data334.id !== "string"){ -const err643 = {instancePath:instancePath+"/items/" + i0+"/permission/id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err643]; -} -else { -vErrors.push(err643); -} -errors++; -} -} -if(data334.agent_id !== undefined){ -if(typeof data334.agent_id !== "string"){ -const err644 = {instancePath:instancePath+"/items/" + i0+"/permission/agent_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err644]; -} -else { -vErrors.push(err644); -} -errors++; -} -} -if(data334.operation_id !== undefined){ -if(typeof data334.operation_id !== "string"){ -const err645 = {instancePath:instancePath+"/items/" + i0+"/permission/operation_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err645]; -} -else { -vErrors.push(err645); -} -errors++; -} -} -if(data334.operation !== undefined){ -if(typeof data334.operation !== "string"){ -const err646 = {instancePath:instancePath+"/items/" + i0+"/permission/operation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err646]; -} -else { -vErrors.push(err646); -} -errors++; -} -} -if(data334.canonical_path !== undefined){ -if(typeof data334.canonical_path !== "string"){ -const err647 = {instancePath:instancePath+"/items/" + i0+"/permission/canonical_path",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err647]; -} -else { -vErrors.push(err647); -} -errors++; -} -} -if(data334.request_digest !== undefined){ -if(typeof data334.request_digest !== "string"){ -const err648 = {instancePath:instancePath+"/items/" + i0+"/permission/request_digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err648]; -} -else { -vErrors.push(err648); -} -errors++; -} -} -if(data334.capability_id !== undefined){ -if(typeof data334.capability_id !== "string"){ -const err649 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err649]; -} -else { -vErrors.push(err649); -} -errors++; -} -} -if(data334.capability_generation !== undefined){ -let data342 = data334.capability_generation; -if(typeof data342 === "string"){ -if(!pattern0.test(data342)){ -const err650 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err650]; -} -else { -vErrors.push(err650); -} -errors++; -} -if(!(formats0.validate(data342))){ -const err651 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err651]; -} -else { -vErrors.push(err651); -} -errors++; -} -} -else { -const err652 = {instancePath:instancePath+"/items/" + i0+"/permission/capability_generation",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err652]; -} -else { -vErrors.push(err652); -} -errors++; -} -} -if(data334.status !== undefined){ -if(typeof data334.status !== "string"){ -const err653 = {instancePath:instancePath+"/items/" + i0+"/permission/status",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err653]; -} -else { -vErrors.push(err653); -} -errors++; -} -} -if(data334.command !== undefined){ -if(typeof data334.command !== "string"){ -const err654 = {instancePath:instancePath+"/items/" + i0+"/permission/command",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err654]; -} -else { -vErrors.push(err654); -} -errors++; -} -} -if(data334.rule !== undefined){ -if(typeof data334.rule !== "string"){ -const err655 = {instancePath:instancePath+"/items/" + i0+"/permission/rule",schemaPath:"#/properties/items/items/allOf/1/oneOf/6/properties/permission/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err655]; -} -else { -vErrors.push(err655); -} -errors++; -} -} -} -} -} -else { -const err656 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/6/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err656]; -} -else { -vErrors.push(err656); -} -errors++; -} -var _valid0 = _errs732 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 6]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 6; -} -const _errs760 = errors; -if(data5 && typeof data5 == "object" && !Array.isArray(data5)){ -if(data5.body === undefined){ -const err657 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/7/required",keyword:"required",params:{missingProperty: "body"},message:"must have required property '"+"body"+"'"}; -if(vErrors === null){ -vErrors = [err657]; -} -else { -vErrors.push(err657); -} -errors++; -} -if(data5.body !== undefined){ -let data346 = data5.body; -if((data346 !== null) && (!(data346 && typeof data346 == "object" && !Array.isArray(data346)))){ -const err658 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err658]; -} -else { -vErrors.push(err658); -} -errors++; -} -if(data346 && typeof data346 == "object" && !Array.isArray(data346)){ -if(data346.reference_id === undefined){ -const err659 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err659]; -} -else { -vErrors.push(err659); -} -errors++; -} -if(data346.digest === undefined){ -const err660 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err660]; -} -else { -vErrors.push(err660); -} -errors++; -} -if(data346.size === undefined){ -const err661 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err661]; -} -else { -vErrors.push(err661); -} -errors++; -} -if(data346.media_type === undefined){ -const err662 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err662]; -} -else { -vErrors.push(err662); -} -errors++; -} -if(data346.source === undefined){ -const err663 = {instancePath:instancePath+"/items/" + i0+"/body",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err663]; -} -else { -vErrors.push(err663); -} -errors++; -} -if(data346.text !== undefined){ -let data347 = data346.text; -if((data347 !== null) && (typeof data347 !== "string")){ -const err664 = {instancePath:instancePath+"/items/" + i0+"/body/text",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/text/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err664]; -} -else { -vErrors.push(err664); -} -errors++; -} -} -if(data346.binary !== undefined){ -let data348 = data346.binary; -if((typeof data348 !== "string") && (data348 !== null)){ -const err665 = {instancePath:instancePath+"/items/" + i0+"/body/binary",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/binary/type",keyword:"type",params:{type: schema156.properties.items.items.allOf[1].oneOf[7].properties.body.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err665]; -} -else { -vErrors.push(err665); -} -errors++; -} -} -if(data346.reference_id !== undefined){ -if(typeof data346.reference_id !== "string"){ -const err666 = {instancePath:instancePath+"/items/" + i0+"/body/reference_id",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err666]; -} -else { -vErrors.push(err666); -} -errors++; -} -} -if(data346.digest !== undefined){ -if(typeof data346.digest !== "string"){ -const err667 = {instancePath:instancePath+"/items/" + i0+"/body/digest",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err667]; -} -else { -vErrors.push(err667); -} -errors++; -} -} -if(data346.size !== undefined){ -let data351 = data346.size; -if(typeof data351 === "string"){ -if(!pattern0.test(data351)){ -const err668 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err668]; -} -else { -vErrors.push(err668); -} -errors++; -} -if(!(formats0.validate(data351))){ -const err669 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err669]; -} -else { -vErrors.push(err669); -} -errors++; -} -} -else { -const err670 = {instancePath:instancePath+"/items/" + i0+"/body/size",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err670]; -} -else { -vErrors.push(err670); -} -errors++; -} -} -if(data346.media_type !== undefined){ -if(typeof data346.media_type !== "string"){ -const err671 = {instancePath:instancePath+"/items/" + i0+"/body/media_type",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err671]; -} -else { -vErrors.push(err671); -} -errors++; -} -} -if(data346.source !== undefined){ -if(typeof data346.source !== "string"){ -const err672 = {instancePath:instancePath+"/items/" + i0+"/body/source",schemaPath:"#/properties/items/items/allOf/1/oneOf/7/properties/body/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err672]; -} -else { -vErrors.push(err672); -} -errors++; -} -} -} -} -} -else { -const err673 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf/7/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err673]; -} -else { -vErrors.push(err673); -} -errors++; -} -var _valid0 = _errs760 === errors; -if(_valid0 && valid42){ -valid42 = false; -passing0 = [passing0, 7]; -} -else { -if(_valid0){ -valid42 = true; -passing0 = 7; -} -} -} -} -} -} -} -} -if(!valid42){ -const err674 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/allOf/1/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"}; -if(vErrors === null){ -vErrors = [err674]; -} -else { -vErrors.push(err674); -} -errors++; -} -else { -errors = _errs386; -if(vErrors !== null){ -if(_errs386){ -vErrors.length = _errs386; -} -else { -vErrors = null; -} -} -} -} -} -} -if(data.next_cursor !== undefined){ -let data354 = data.next_cursor; -if((data354 !== null) && (!(data354 && typeof data354 == "object" && !Array.isArray(data354)))){ -const err675 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema156.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err675]; -} -else { -vErrors.push(err675); -} -errors++; -} -if(data354 && typeof data354 == "object" && !Array.isArray(data354)){ -if(data354.root_id === undefined){ -const err676 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err676]; -} -else { -vErrors.push(err676); -} -errors++; -} -if(data354.collection === undefined){ -const err677 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err677]; -} -else { -vErrors.push(err677); -} -errors++; -} -if(data354.revision === undefined){ -const err678 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err678]; -} -else { -vErrors.push(err678); -} -errors++; -} -if(data354.offset === undefined){ -const err679 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err679]; -} -else { -vErrors.push(err679); -} -errors++; -} -if(data354.root_id !== undefined){ -if(typeof data354.root_id !== "string"){ -const err680 = {instancePath:instancePath+"/next_cursor/root_id",schemaPath:"#/properties/next_cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err680]; -} -else { -vErrors.push(err680); -} -errors++; -} -} -if(data354.collection !== undefined){ -if(typeof data354.collection !== "string"){ -const err681 = {instancePath:instancePath+"/next_cursor/collection",schemaPath:"#/properties/next_cursor/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err681]; -} -else { -vErrors.push(err681); -} -errors++; -} -} -if(data354.revision !== undefined){ -let data357 = data354.revision; -if(typeof data357 === "string"){ -if(!pattern0.test(data357)){ -const err682 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err682]; -} -else { -vErrors.push(err682); -} -errors++; -} -if(!(formats0.validate(data357))){ -const err683 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err683]; -} -else { -vErrors.push(err683); -} -errors++; -} -} -else { -const err684 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err684]; -} -else { -vErrors.push(err684); -} -errors++; -} -} -if(data354.offset !== undefined){ -let data358 = data354.offset; -if(typeof data358 === "string"){ -if(!pattern0.test(data358)){ -const err685 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err685]; -} -else { -vErrors.push(err685); -} -errors++; -} -if(!(formats0.validate(data358))){ -const err686 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err686]; -} -else { -vErrors.push(err686); -} -errors++; -} -} -else { -const err687 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err687]; -} -else { -vErrors.push(err687); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err688 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err688]; -} -else { -vErrors.push(err688); -} -errors++; -} -} -} -else { -const err689 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err689]; -} -else { -vErrors.push(err689); -} -errors++; -} -validate155.errors = vErrors; -return errors === 0; -} - -export const RootCollectionParams = validate156; -const schema157 = {"type":"object","properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"cursor":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"collection":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","collection","revision","offset"],"additionalProperties":true},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RootCollectionParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RootCollectionParams","required":["root_id","collection","limit","max_bytes"],"additionalProperties":true}; - -function validate156(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootCollectionParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.collection === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.limit === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.max_bytes === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.collection !== undefined){ -if(typeof data.collection !== "string"){ -const err5 = {instancePath:instancePath+"/collection",schemaPath:"#/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema157.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.root_id === undefined){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.collection === undefined){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "collection"},message:"must have required property '"+"collection"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.revision === undefined){ -const err9 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.offset === undefined){ -const err10 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.root_id !== undefined){ -if(typeof data2.root_id !== "string"){ -const err11 = {instancePath:instancePath+"/cursor/root_id",schemaPath:"#/properties/cursor/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data2.collection !== undefined){ -if(typeof data2.collection !== "string"){ -const err12 = {instancePath:instancePath+"/cursor/collection",schemaPath:"#/properties/cursor/properties/collection/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data2.revision !== undefined){ -let data5 = data2.revision; -if(typeof data5 === "string"){ -if(!pattern0.test(data5)){ -const err13 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(!(formats0.validate(data5))){ -const err14 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -else { -const err15 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data2.offset !== undefined){ -let data6 = data2.offset; -if(typeof data6 === "string"){ -if(!pattern0.test(data6)){ -const err16 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(formats0.validate(data6))){ -const err17 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -else { -const err18 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data7 = data.limit; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err19 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data8 = data.max_bytes; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err20 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -validate156.errors = vErrors; -return errors === 0; -} - -export const RootIDResult = validate157; -const schema158 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootIDResult","$schema":"http://json-schema.org/draft-07/schema#","title":"RootIDResult","required":["root_id"],"additionalProperties":true}; - -function validate157(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootIDResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate157.errors = vErrors; -return errors === 0; -} - -export const RootParams = validate158; -const schema159 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RootParams","required":["root_id"],"additionalProperties":true}; - -function validate158(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate158.errors = vErrors; -return errors === 0; -} - -export const RootSnapshot = validate159; -const schema160 = {"type":"object","properties":{"collection_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"active_turns":{"type":"object","additionalProperties":{"type":"string"}},"omitted":{"type":"object","additionalProperties":{"type":"boolean"}},"message_seqs":{"type":["null","array"],"items":{"type":"integer"}},"first_message_seq":{"type":"integer"},"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"meta":{"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"definition_revision":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"goal":{"type":"string"},"forked_from":{"type":"string"},"fork_seq":{"type":"integer"},"tags":{"type":["null","array"],"items":{"type":"string"}},"archived":{"type":"boolean"},"pinned":{"type":"boolean"},"effort":{"type":"string"},"usage_in":{"type":"integer"},"usage_cached":{"type":"integer"},"usage_out":{"type":"integer"},"updated_at":{"type":"string"}},"required":["execution_engine","definition","definition_revision","id","kind","title","model","provider","cwd","goal","forked_from","fork_seq","tags","archived","pinned","effort","usage_in","usage_cached","usage_out","updated_at"],"additionalProperties":true},"messages":{"type":["null","array"],"items":{"type":"object","properties":{"presentation":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"},"context_part_index":{"type":"integer"},"screenshot_part_index":{"type":["null","integer"]}},"required":["context_attachment_id","elements","element_count","context_part_index"],"additionalProperties":true},"version":{"type":"integer"},"turn_id":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"start":{"type":"integer"},"end":{"type":"integer"},"text":{"type":"string"},"tool_name":{"type":"string"},"status":{"type":"string"},"call_id":{"type":"string"},"hosts":{"type":["null","array"],"items":{"type":"object","properties":{"invocation_id":{"type":"string"},"name":{"type":"string"},"summary":{"type":"string"},"status":{"type":"string"},"duration":{"type":"string"},"error":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true}},"required":["invocation_id","name","status"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["id","kind"],"additionalProperties":true}},"omitted":{"type":"integer"}},"required":["version"],"additionalProperties":true},"role":{"type":"string"},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}}]},"tool_calls":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"arguments":{"type":"string"}},"required":["name","arguments"],"additionalProperties":true},"duration_ms":{"type":"integer"},"exit_code":{"type":"integer"}},"required":["id","type","function"],"additionalProperties":true}},"tool_call_id":{"type":"string"},"name":{"type":"string"},"authored":{"type":"boolean"},"sent_at":{"type":["null","string"]},"usage":{"type":["null","object"],"properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true},"model":{"type":"string"},"rewound_from":{"type":"string"},"call_id":{"type":"string"}},"required":["role","content"],"additionalProperties":true}},"presentation":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":true}},"agent_presentations":{"type":"object","additionalProperties":{"type":["null","array"],"items":{"type":"object","properties":{"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"payload":true},"required":["seq","kind","payload"],"additionalProperties":true}}},"agents":{"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"last_turn":{"type":["null","object"],"properties":{"turn_id":{"type":"string"},"status":{"type":"string"},"started_at":{"type":"string"},"finished_at":{"type":"string"},"event_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"error":{"type":"string"},"error_truncated":{"type":"boolean"},"error_details":{"type":["null","object"],"properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true},"model_calls":{"type":"integer"},"compactions":{"type":"integer"},"last_activity_at":{"type":"string"}},"required":["status","event_seq"],"additionalProperties":true},"id":{"type":"string"},"root_id":{"type":"string"},"parent_id":{"type":"string"},"name":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"cwd":{"type":"string"},"report":{"type":"string"},"status":{"type":"string"},"pending_mail":{"type":"integer"},"lifecycle_phase":{"type":"string"},"blocking_reason":{"type":"string"},"terminal_cause":{"type":"string"},"allowed_controls":{"type":["null","array"],"items":{"type":"string"}}},"required":["execution_engine","id","root_id","parent_id","name","model","provider","effort","cwd","report","status","pending_mail","lifecycle_phase","blocking_reason","terminal_cause","allowed_controls"],"additionalProperties":true}},"inbox":{"type":["null","array"],"items":{"type":"object","properties":{"delivery_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"origin":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"steer_turn_id":{"type":"string"},"preview":{"type":["null","object"],"properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"truncated":{"type":"boolean"},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string"},"name":{"type":"string"},"content":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["kind","content"],"additionalProperties":true}},"attachment_count":{"type":"integer"}},"required":["text"],"additionalProperties":true},"root_id":{"type":"string"},"agent_id":{"type":"string"},"seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"kind":{"type":"string"},"status":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["root_id","agent_id","seq","kind","status","payload"],"additionalProperties":true}},"blackboard":{"type":["null","array"],"items":{"type":"object","properties":{"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"author_agent_id":{"type":"string"},"payload":{"type":"object","properties":{"inline":true,"text":{"type":["null","string"]},"binary":{"type":["string","null"],"contentEncoding":"base64"},"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size","media_type","source"],"additionalProperties":true}},"required":["key","version","author_agent_id","payload"],"additionalProperties":true}},"budgets":{"type":["null","array"],"items":{"type":"object","properties":{"agent_id":{"type":"string"},"state":{"type":"object","properties":{"kind":{"type":"string"},"limit":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"remaining":{"type":["string","null"],"pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"uncertain":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"incomplete":{"type":"boolean"}},"required":["kind","limit","used","reserved","remaining","uncertain","incomplete"],"additionalProperties":true}},"required":["agent_id","state"],"additionalProperties":true}},"accounting":{"type":"object","properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"capabilities":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"issuer_agent_id":{"type":"string"},"operations":{"type":["null","array"],"items":{"type":"string"}},"scopes":{"type":["null","array"],"items":{"type":"string"}},"file_scope":{"type":"string"},"file_issuer_id":{"type":"string"},"file_issuer_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"mcp":{"type":["null","array"],"items":{"type":"object","properties":{"server":{"type":"string"},"tool":{"type":"string"},"definition":{"type":"string"}},"required":["server","tool","definition"],"additionalProperties":true}},"mcp_all":{"type":"boolean"},"browser":{"type":["null","object"],"properties":{"provider_id":{"type":"string"},"provider_epoch":{"type":"string"},"tab_id":{"type":"string"},"tab_generation":{"type":"string"},"profile_id":{"type":"string"},"attachment_id":{"type":"string"},"attachment_generation":{"type":"string"},"rights":{"type":["null","array"],"items":{"type":"string"}},"preview":{"type":["null","object"],"properties":{"host_id":{"type":"string"},"host_identity":{"type":"string"},"connection_generation":{"type":"string"},"environment_id":{"type":"string"},"loopback":{"type":"string"},"ports":{"type":["null","array"],"items":{"type":"integer"}}},"required":["host_id","host_identity","connection_generation","environment_id","loopback","ports"],"additionalProperties":true}},"required":["provider_id","provider_epoch","tab_id","tab_generation","profile_id","rights"],"additionalProperties":true},"browser_issuer_id":{"type":"string"},"browser_issuer_generation":{"type":"integer"},"browser_delegation_only":{"type":"boolean"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"expires_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","root_id","agent_id","issuer_agent_id","operations","scopes","mcp","mcp_all","generation","status","expires_at","created_at","updated_at"],"additionalProperties":true}},"schedules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":true}},"upcoming_schedules":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"next_fire":{"type":"string"},"prompt":{"type":"string"},"prompt_truncated":{"type":"boolean"}},"required":["id","next_fire","prompt"],"additionalProperties":true}},"upcoming_schedule_count":{"type":["null","integer"]},"permissions":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"agent_id":{"type":"string"},"operation_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"capability_id":{"type":"string"},"capability_generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"status":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"}},"required":["id","agent_id","operation_id","operation","canonical_path","request_digest","capability_id","capability_generation","status","command","rule"],"additionalProperties":true}},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"turn_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"sender_agent_id":{"type":"string"},"inbox_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"inbox_kind":{"type":"string"},"delivery":{"type":"string"},"message_id":{"type":"string"},"phase":{"type":"string"},"status":{"type":"string"},"terminal_cause":{"type":"string"},"command_client_id":{"type":"string"},"command_id":{"type":"string"},"operation_id":{"type":"string"},"trace_id":{"type":"string"},"schedule_id":{"type":"integer"},"slot":{"type":"string"},"error":{"type":"string"},"model_call":{"type":["null","object"],"properties":{"id":{"type":"string"},"logical_id":{"type":"string"},"number":{"type":"integer"},"purpose":{"type":"string"},"usage_source":{"type":"string"},"cost_source":{"type":"string"},"tokens":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"elapsed_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"exhausted":{"type":"boolean"}},"required":["id","logical_id","number","purpose","usage_source","cost_source","tokens","cost_micros","elapsed_millis","exhausted"],"additionalProperties":true},"acknowledged_inbox":{"type":"array","items":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"subscription_id":{"type":"string"},"key":{"type":"string"},"version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"expected_version":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"restored":{"type":["null","array"],"items":{"type":"string"}},"not_restored":{"type":["null","array"],"items":{"type":"object","properties":{"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","reason"],"additionalProperties":true}},"attempt":{"type":"string"},"budget_kind":{"type":"string"},"amount":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"used":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reserved":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"capability_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"permission_id":{"type":"string"},"operation":{"type":"string"},"canonical_path":{"type":"string"},"request_digest":{"type":"string"},"command":{"type":"string"},"rule":{"type":"string"},"rule_source":{"type":"string"},"question_id":{"type":"string"},"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"},"questions":{"type":["null","array"],"items":{"type":"object","properties":{"question":{"type":"string"},"options":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"description":{"type":"string"},"recommended":{"type":"boolean"}},"required":["label"],"additionalProperties":true}},"multiple":{"type":"boolean"}},"required":["question"],"additionalProperties":true}},"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"},"answers":{"type":["null","array"],"items":{"type":"object","properties":{"answer":{"type":["null","array"],"items":{"type":"string"}},"dismissed":{"type":"boolean"}},"additionalProperties":true}}},"additionalProperties":true}},"permission_mode":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RootSnapshot","$schema":"http://json-schema.org/draft-07/schema#","title":"RootSnapshot","required":["active_turns","message_seqs","history_revision","root_id","cursor","meta","messages","presentation","agent_presentations","agents","inbox","blackboard","budgets","capabilities","schedules","permissions","questions"],"additionalProperties":true}; - -function validate159(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RootSnapshot" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.active_turns === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "active_turns"},message:"must have required property '"+"active_turns"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.message_seqs === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "message_seqs"},message:"must have required property '"+"message_seqs"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.history_revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.root_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.cursor === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.meta === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "meta"},message:"must have required property '"+"meta"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.messages === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "messages"},message:"must have required property '"+"messages"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.presentation === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "presentation"},message:"must have required property '"+"presentation"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.agent_presentations === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_presentations"},message:"must have required property '"+"agent_presentations"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.agents === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agents"},message:"must have required property '"+"agents"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.inbox === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "inbox"},message:"must have required property '"+"inbox"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.blackboard === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "blackboard"},message:"must have required property '"+"blackboard"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.budgets === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "budgets"},message:"must have required property '"+"budgets"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.capabilities === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "capabilities"},message:"must have required property '"+"capabilities"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data.schedules === undefined){ -const err14 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedules"},message:"must have required property '"+"schedules"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data.permissions === undefined){ -const err15 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "permissions"},message:"must have required property '"+"permissions"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data.questions === undefined){ -const err16 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "questions"},message:"must have required property '"+"questions"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data.collection_revision !== undefined){ -let data0 = data.collection_revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err17 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err18 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -else { -const err19 = {instancePath:instancePath+"/collection_revision",schemaPath:"#/properties/collection_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.active_turns !== undefined){ -let data1 = data.active_turns; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -for(const key0 in data1){ -if(typeof data1[key0] !== "string"){ -const err20 = {instancePath:instancePath+"/active_turns/" + key0.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/active_turns/additionalProperties/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -} -else { -const err21 = {instancePath:instancePath+"/active_turns",schemaPath:"#/properties/active_turns/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.omitted !== undefined){ -let data3 = data.omitted; -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -for(const key1 in data3){ -if(typeof data3[key1] !== "boolean"){ -const err22 = {instancePath:instancePath+"/omitted/" + key1.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/omitted/additionalProperties/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath:instancePath+"/omitted",schemaPath:"#/properties/omitted/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data.message_seqs !== undefined){ -let data5 = data.message_seqs; -if((data5 !== null) && (!(Array.isArray(data5)))){ -const err24 = {instancePath:instancePath+"/message_seqs",schemaPath:"#/properties/message_seqs/type",keyword:"type",params:{type: schema160.properties.message_seqs.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(Array.isArray(data5)){ -const len0 = data5.length; -for(let i0=0; i0<len0; i0++){ -let data6 = data5[i0]; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err25 = {instancePath:instancePath+"/message_seqs/" + i0,schemaPath:"#/properties/message_seqs/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data.first_message_seq !== undefined){ -let data7 = data.first_message_seq; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err26 = {instancePath:instancePath+"/first_message_seq",schemaPath:"#/properties/first_message_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data.history_revision !== undefined){ -let data8 = data.history_revision; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err27 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err28 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -else { -const err29 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err30 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data10 = data.cursor; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err31 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err32 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -else { -const err33 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -if(data.meta !== undefined){ -let data11 = data.meta; -if(data11 && typeof data11 == "object" && !Array.isArray(data11)){ -if(data11.execution_engine === undefined){ -const err34 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -if(data11.definition === undefined){ -const err35 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(data11.definition_revision === undefined){ -const err36 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "definition_revision"},message:"must have required property '"+"definition_revision"+"'"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(data11.id === undefined){ -const err37 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -if(data11.kind === undefined){ -const err38 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(data11.title === undefined){ -const err39 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -if(data11.model === undefined){ -const err40 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(data11.provider === undefined){ -const err41 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(data11.cwd === undefined){ -const err42 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -if(data11.goal === undefined){ -const err43 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -if(data11.forked_from === undefined){ -const err44 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "forked_from"},message:"must have required property '"+"forked_from"+"'"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(data11.fork_seq === undefined){ -const err45 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "fork_seq"},message:"must have required property '"+"fork_seq"+"'"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -if(data11.tags === undefined){ -const err46 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "tags"},message:"must have required property '"+"tags"+"'"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -if(data11.archived === undefined){ -const err47 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(data11.pinned === undefined){ -const err48 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -if(data11.effort === undefined){ -const err49 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -if(data11.usage_in === undefined){ -const err50 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_in"},message:"must have required property '"+"usage_in"+"'"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data11.usage_cached === undefined){ -const err51 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_cached"},message:"must have required property '"+"usage_cached"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data11.usage_out === undefined){ -const err52 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "usage_out"},message:"must have required property '"+"usage_out"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data11.updated_at === undefined){ -const err53 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data11.execution_engine !== undefined){ -if(typeof data11.execution_engine !== "string"){ -const err54 = {instancePath:instancePath+"/meta/execution_engine",schemaPath:"#/properties/meta/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data11.definition !== undefined){ -if(typeof data11.definition !== "string"){ -const err55 = {instancePath:instancePath+"/meta/definition",schemaPath:"#/properties/meta/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data11.definition_revision !== undefined){ -if(typeof data11.definition_revision !== "string"){ -const err56 = {instancePath:instancePath+"/meta/definition_revision",schemaPath:"#/properties/meta/properties/definition_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -} -if(data11.id !== undefined){ -if(typeof data11.id !== "string"){ -const err57 = {instancePath:instancePath+"/meta/id",schemaPath:"#/properties/meta/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -} -if(data11.kind !== undefined){ -if(typeof data11.kind !== "string"){ -const err58 = {instancePath:instancePath+"/meta/kind",schemaPath:"#/properties/meta/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data11.title !== undefined){ -if(typeof data11.title !== "string"){ -const err59 = {instancePath:instancePath+"/meta/title",schemaPath:"#/properties/meta/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data11.model !== undefined){ -if(typeof data11.model !== "string"){ -const err60 = {instancePath:instancePath+"/meta/model",schemaPath:"#/properties/meta/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data11.provider !== undefined){ -if(typeof data11.provider !== "string"){ -const err61 = {instancePath:instancePath+"/meta/provider",schemaPath:"#/properties/meta/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data11.cwd !== undefined){ -if(typeof data11.cwd !== "string"){ -const err62 = {instancePath:instancePath+"/meta/cwd",schemaPath:"#/properties/meta/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -} -if(data11.goal !== undefined){ -if(typeof data11.goal !== "string"){ -const err63 = {instancePath:instancePath+"/meta/goal",schemaPath:"#/properties/meta/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -} -if(data11.forked_from !== undefined){ -if(typeof data11.forked_from !== "string"){ -const err64 = {instancePath:instancePath+"/meta/forked_from",schemaPath:"#/properties/meta/properties/forked_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -if(data11.fork_seq !== undefined){ -let data23 = data11.fork_seq; -if(!((typeof data23 == "number") && (!(data23 % 1) && !isNaN(data23)))){ -const err65 = {instancePath:instancePath+"/meta/fork_seq",schemaPath:"#/properties/meta/properties/fork_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -} -if(data11.tags !== undefined){ -let data24 = data11.tags; -if((data24 !== null) && (!(Array.isArray(data24)))){ -const err66 = {instancePath:instancePath+"/meta/tags",schemaPath:"#/properties/meta/properties/tags/type",keyword:"type",params:{type: schema160.properties.meta.properties.tags.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(Array.isArray(data24)){ -const len1 = data24.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data24[i1] !== "string"){ -const err67 = {instancePath:instancePath+"/meta/tags/" + i1,schemaPath:"#/properties/meta/properties/tags/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -} -if(data11.archived !== undefined){ -if(typeof data11.archived !== "boolean"){ -const err68 = {instancePath:instancePath+"/meta/archived",schemaPath:"#/properties/meta/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -if(data11.pinned !== undefined){ -if(typeof data11.pinned !== "boolean"){ -const err69 = {instancePath:instancePath+"/meta/pinned",schemaPath:"#/properties/meta/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data11.effort !== undefined){ -if(typeof data11.effort !== "string"){ -const err70 = {instancePath:instancePath+"/meta/effort",schemaPath:"#/properties/meta/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data11.usage_in !== undefined){ -let data29 = data11.usage_in; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err71 = {instancePath:instancePath+"/meta/usage_in",schemaPath:"#/properties/meta/properties/usage_in/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data11.usage_cached !== undefined){ -let data30 = data11.usage_cached; -if(!((typeof data30 == "number") && (!(data30 % 1) && !isNaN(data30)))){ -const err72 = {instancePath:instancePath+"/meta/usage_cached",schemaPath:"#/properties/meta/properties/usage_cached/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data11.usage_out !== undefined){ -let data31 = data11.usage_out; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err73 = {instancePath:instancePath+"/meta/usage_out",schemaPath:"#/properties/meta/properties/usage_out/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data11.updated_at !== undefined){ -if(typeof data11.updated_at !== "string"){ -const err74 = {instancePath:instancePath+"/meta/updated_at",schemaPath:"#/properties/meta/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -} -else { -const err75 = {instancePath:instancePath+"/meta",schemaPath:"#/properties/meta/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.messages !== undefined){ -let data33 = data.messages; -if((data33 !== null) && (!(Array.isArray(data33)))){ -const err76 = {instancePath:instancePath+"/messages",schemaPath:"#/properties/messages/type",keyword:"type",params:{type: schema160.properties.messages.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -if(Array.isArray(data33)){ -const len2 = data33.length; -for(let i2=0; i2<len2; i2++){ -let data34 = data33[i2]; -if(data34 && typeof data34 == "object" && !Array.isArray(data34)){ -if(data34.role === undefined){ -const err77 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "role"},message:"must have required property '"+"role"+"'"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -if(data34.content === undefined){ -const err78 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -if(data34.presentation !== undefined){ -let data35 = data34.presentation; -if((data35 !== null) && (!(data35 && typeof data35 == "object" && !Array.isArray(data35)))){ -const err79 = {instancePath:instancePath+"/messages/" + i2+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -if(data35 && typeof data35 == "object" && !Array.isArray(data35)){ -if(data35.version === undefined){ -const err80 = {instancePath:instancePath+"/messages/" + i2+"/presentation",schemaPath:"#/properties/messages/items/properties/presentation/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err80]; -} -else { -vErrors.push(err80); -} -errors++; -} -if(data35.design_context !== undefined){ -let data36 = data35.design_context; -if((data36 !== null) && (!(data36 && typeof data36 == "object" && !Array.isArray(data36)))){ -const err81 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err81]; -} -else { -vErrors.push(err81); -} -errors++; -} -if(data36 && typeof data36 == "object" && !Array.isArray(data36)){ -if(data36.context_attachment_id === undefined){ -const err82 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err82]; -} -else { -vErrors.push(err82); -} -errors++; -} -if(data36.elements === undefined){ -const err83 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err83]; -} -else { -vErrors.push(err83); -} -errors++; -} -if(data36.element_count === undefined){ -const err84 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err84]; -} -else { -vErrors.push(err84); -} -errors++; -} -if(data36.context_part_index === undefined){ -const err85 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/required",keyword:"required",params:{missingProperty: "context_part_index"},message:"must have required property '"+"context_part_index"+"'"}; -if(vErrors === null){ -vErrors = [err85]; -} -else { -vErrors.push(err85); -} -errors++; -} -if(data36.context_attachment_id !== undefined){ -if(typeof data36.context_attachment_id !== "string"){ -const err86 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/context_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err86]; -} -else { -vErrors.push(err86); -} -errors++; -} -} -if(data36.screenshot_attachment_id !== undefined){ -if(typeof data36.screenshot_attachment_id !== "string"){ -const err87 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/screenshot_attachment_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err87]; -} -else { -vErrors.push(err87); -} -errors++; -} -} -if(data36.elements !== undefined){ -let data39 = data36.elements; -if((data39 !== null) && (!(Array.isArray(data39)))){ -const err88 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err88]; -} -else { -vErrors.push(err88); -} -errors++; -} -if(Array.isArray(data39)){ -const len3 = data39.length; -for(let i3=0; i3<len3; i3++){ -let data40 = data39[i3]; -if(data40 && typeof data40 == "object" && !Array.isArray(data40)){ -if(data40.label === undefined){ -const err89 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err89]; -} -else { -vErrors.push(err89); -} -errors++; -} -if(data40.label !== undefined){ -if(typeof data40.label !== "string"){ -const err90 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3+"/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err90]; -} -else { -vErrors.push(err90); -} -errors++; -} -} -if(data40.selector !== undefined){ -if(typeof data40.selector !== "string"){ -const err91 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3+"/selector",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err91]; -} -else { -vErrors.push(err91); -} -errors++; -} -} -} -else { -const err92 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/elements/" + i3,schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err92]; -} -else { -vErrors.push(err92); -} -errors++; -} -} -} -} -if(data36.element_count !== undefined){ -let data43 = data36.element_count; -if(!((typeof data43 == "number") && (!(data43 % 1) && !isNaN(data43)))){ -const err93 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/element_count",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err93]; -} -else { -vErrors.push(err93); -} -errors++; -} -} -if(data36.page_url !== undefined){ -if(typeof data36.page_url !== "string"){ -const err94 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/page_url",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err94]; -} -else { -vErrors.push(err94); -} -errors++; -} -} -if(data36.page_title !== undefined){ -if(typeof data36.page_title !== "string"){ -const err95 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/page_title",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err95]; -} -else { -vErrors.push(err95); -} -errors++; -} -} -if(data36.context_part_index !== undefined){ -let data46 = data36.context_part_index; -if(!((typeof data46 == "number") && (!(data46 % 1) && !isNaN(data46)))){ -const err96 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/context_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/context_part_index/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err96]; -} -else { -vErrors.push(err96); -} -errors++; -} -} -if(data36.screenshot_part_index !== undefined){ -let data47 = data36.screenshot_part_index; -if((data47 !== null) && (!((typeof data47 == "number") && (!(data47 % 1) && !isNaN(data47))))){ -const err97 = {instancePath:instancePath+"/messages/" + i2+"/presentation/design_context/screenshot_part_index",schemaPath:"#/properties/messages/items/properties/presentation/properties/design_context/properties/screenshot_part_index/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.design_context.properties.screenshot_part_index.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err97]; -} -else { -vErrors.push(err97); -} -errors++; -} -} -} -} -if(data35.version !== undefined){ -let data48 = data35.version; -if(!((typeof data48 == "number") && (!(data48 % 1) && !isNaN(data48)))){ -const err98 = {instancePath:instancePath+"/messages/" + i2+"/presentation/version",schemaPath:"#/properties/messages/items/properties/presentation/properties/version/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err98]; -} -else { -vErrors.push(err98); -} -errors++; -} -} -if(data35.turn_id !== undefined){ -if(typeof data35.turn_id !== "string"){ -const err99 = {instancePath:instancePath+"/messages/" + i2+"/presentation/turn_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err99]; -} -else { -vErrors.push(err99); -} -errors++; -} -} -if(data35.parts !== undefined){ -let data50 = data35.parts; -if((data50 !== null) && (!(Array.isArray(data50)))){ -const err100 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err100]; -} -else { -vErrors.push(err100); -} -errors++; -} -if(Array.isArray(data50)){ -const len4 = data50.length; -for(let i4=0; i4<len4; i4++){ -let data51 = data50[i4]; -if(data51 && typeof data51 == "object" && !Array.isArray(data51)){ -if(data51.id === undefined){ -const err101 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err101]; -} -else { -vErrors.push(err101); -} -errors++; -} -if(data51.kind === undefined){ -const err102 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err102]; -} -else { -vErrors.push(err102); -} -errors++; -} -if(data51.id !== undefined){ -if(typeof data51.id !== "string"){ -const err103 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err103]; -} -else { -vErrors.push(err103); -} -errors++; -} -} -if(data51.kind !== undefined){ -if(typeof data51.kind !== "string"){ -const err104 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/kind",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err104]; -} -else { -vErrors.push(err104); -} -errors++; -} -} -if(data51.start !== undefined){ -let data54 = data51.start; -if(!((typeof data54 == "number") && (!(data54 % 1) && !isNaN(data54)))){ -const err105 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/start",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/start/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err105]; -} -else { -vErrors.push(err105); -} -errors++; -} -} -if(data51.end !== undefined){ -let data55 = data51.end; -if(!((typeof data55 == "number") && (!(data55 % 1) && !isNaN(data55)))){ -const err106 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/end",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/end/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err106]; -} -else { -vErrors.push(err106); -} -errors++; -} -} -if(data51.text !== undefined){ -if(typeof data51.text !== "string"){ -const err107 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/text",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err107]; -} -else { -vErrors.push(err107); -} -errors++; -} -} -if(data51.tool_name !== undefined){ -if(typeof data51.tool_name !== "string"){ -const err108 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/tool_name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/tool_name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err108]; -} -else { -vErrors.push(err108); -} -errors++; -} -} -if(data51.status !== undefined){ -if(typeof data51.status !== "string"){ -const err109 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err109]; -} -else { -vErrors.push(err109); -} -errors++; -} -} -if(data51.call_id !== undefined){ -if(typeof data51.call_id !== "string"){ -const err110 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/call_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err110]; -} -else { -vErrors.push(err110); -} -errors++; -} -} -if(data51.hosts !== undefined){ -let data60 = data51.hosts; -if((data60 !== null) && (!(Array.isArray(data60)))){ -const err111 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err111]; -} -else { -vErrors.push(err111); -} -errors++; -} -if(Array.isArray(data60)){ -const len5 = data60.length; -for(let i5=0; i5<len5; i5++){ -let data61 = data60[i5]; -if(data61 && typeof data61 == "object" && !Array.isArray(data61)){ -if(data61.invocation_id === undefined){ -const err112 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err112]; -} -else { -vErrors.push(err112); -} -errors++; -} -if(data61.name === undefined){ -const err113 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err113]; -} -else { -vErrors.push(err113); -} -errors++; -} -if(data61.status === undefined){ -const err114 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err114]; -} -else { -vErrors.push(err114); -} -errors++; -} -if(data61.invocation_id !== undefined){ -if(typeof data61.invocation_id !== "string"){ -const err115 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/invocation_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err115]; -} -else { -vErrors.push(err115); -} -errors++; -} -} -if(data61.name !== undefined){ -if(typeof data61.name !== "string"){ -const err116 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/name",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err116]; -} -else { -vErrors.push(err116); -} -errors++; -} -} -if(data61.summary !== undefined){ -if(typeof data61.summary !== "string"){ -const err117 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/summary",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/summary/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err117]; -} -else { -vErrors.push(err117); -} -errors++; -} -} -if(data61.status !== undefined){ -if(typeof data61.status !== "string"){ -const err118 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/status",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err118]; -} -else { -vErrors.push(err118); -} -errors++; -} -} -if(data61.duration !== undefined){ -if(typeof data61.duration !== "string"){ -const err119 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/duration",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/duration/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err119]; -} -else { -vErrors.push(err119); -} -errors++; -} -} -if(data61.error !== undefined){ -if(typeof data61.error !== "string"){ -const err120 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/error",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err120]; -} -else { -vErrors.push(err120); -} -errors++; -} -} -if(data61.display !== undefined){ -let data68 = data61.display; -if((data68 !== null) && (!(data68 && typeof data68 == "object" && !Array.isArray(data68)))){ -const err121 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.presentation.properties.parts.items.properties.hosts.items.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err121]; -} -else { -vErrors.push(err121); -} -errors++; -} -if(data68 && typeof data68 == "object" && !Array.isArray(data68)){ -if(data68.target !== undefined){ -if(typeof data68.target !== "string"){ -const err122 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/target",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err122]; -} -else { -vErrors.push(err122); -} -errors++; -} -} -if(data68.command !== undefined){ -if(typeof data68.command !== "string"){ -const err123 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/command",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err123]; -} -else { -vErrors.push(err123); -} -errors++; -} -} -if(data68.query !== undefined){ -if(typeof data68.query !== "string"){ -const err124 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/query",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err124]; -} -else { -vErrors.push(err124); -} -errors++; -} -} -if(data68.child_id !== undefined){ -if(typeof data68.child_id !== "string"){ -const err125 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/child_id",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err125]; -} -else { -vErrors.push(err125); -} -errors++; -} -} -if(data68.label !== undefined){ -if(typeof data68.label !== "string"){ -const err126 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5+"/display/label",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err126]; -} -else { -vErrors.push(err126); -} -errors++; -} -} -} -} -} -else { -const err127 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/hosts/" + i5,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err127]; -} -else { -vErrors.push(err127); -} -errors++; -} -} -} -} -if(data51.omitted !== undefined){ -let data74 = data51.omitted; -if(!((typeof data74 == "number") && (!(data74 % 1) && !isNaN(data74)))){ -const err128 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4+"/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err128]; -} -else { -vErrors.push(err128); -} -errors++; -} -} -} -else { -const err129 = {instancePath:instancePath+"/messages/" + i2+"/presentation/parts/" + i4,schemaPath:"#/properties/messages/items/properties/presentation/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err129]; -} -else { -vErrors.push(err129); -} -errors++; -} -} -} -} -if(data35.omitted !== undefined){ -let data75 = data35.omitted; -if(!((typeof data75 == "number") && (!(data75 % 1) && !isNaN(data75)))){ -const err130 = {instancePath:instancePath+"/messages/" + i2+"/presentation/omitted",schemaPath:"#/properties/messages/items/properties/presentation/properties/omitted/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err130]; -} -else { -vErrors.push(err130); -} -errors++; -} -} -} -} -if(data34.role !== undefined){ -if(typeof data34.role !== "string"){ -const err131 = {instancePath:instancePath+"/messages/" + i2+"/role",schemaPath:"#/properties/messages/items/properties/role/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err131]; -} -else { -vErrors.push(err131); -} -errors++; -} -} -if(data34.content !== undefined){ -let data77 = data34.content; -const _errs167 = errors; -let valid23 = false; -const _errs168 = errors; -if(typeof data77 !== "string"){ -const err132 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf/0/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err132]; -} -else { -vErrors.push(err132); -} -errors++; -} -var _valid0 = _errs168 === errors; -valid23 = valid23 || _valid0; -if(!valid23){ -const _errs170 = errors; -if(Array.isArray(data77)){ -const len6 = data77.length; -for(let i6=0; i6<len6; i6++){ -let data78 = data77[i6]; -if(data78 && typeof data78 == "object" && !Array.isArray(data78)){ -if(data78.type === undefined){ -const err133 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6,schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err133]; -} -else { -vErrors.push(err133); -} -errors++; -} -if(data78.type !== undefined){ -if(typeof data78.type !== "string"){ -const err134 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/type",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err134]; -} -else { -vErrors.push(err134); -} -errors++; -} -} -if(data78.text !== undefined){ -if(typeof data78.text !== "string"){ -const err135 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/text",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err135]; -} -else { -vErrors.push(err135); -} -errors++; -} -} -if(data78.image_url !== undefined){ -let data81 = data78.image_url; -if((data81 !== null) && (!(data81 && typeof data81 == "object" && !Array.isArray(data81)))){ -const err136 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.content.anyOf[1].items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err136]; -} -else { -vErrors.push(err136); -} -errors++; -} -if(data81 && typeof data81 == "object" && !Array.isArray(data81)){ -if(data81.url === undefined){ -const err137 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err137]; -} -else { -vErrors.push(err137); -} -errors++; -} -if(data81.url !== undefined){ -if(typeof data81.url !== "string"){ -const err138 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/image_url/url",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err138]; -} -else { -vErrors.push(err138); -} -errors++; -} -} -} -} -if(data78.w !== undefined){ -let data83 = data78.w; -if(!((typeof data83 == "number") && (!(data83 % 1) && !isNaN(data83)))){ -const err139 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/w",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err139]; -} -else { -vErrors.push(err139); -} -errors++; -} -} -if(data78.h !== undefined){ -let data84 = data78.h; -if(!((typeof data84 == "number") && (!(data84 % 1) && !isNaN(data84)))){ -const err140 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6+"/h",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err140]; -} -else { -vErrors.push(err140); -} -errors++; -} -} -} -else { -const err141 = {instancePath:instancePath+"/messages/" + i2+"/content/" + i6,schemaPath:"#/properties/messages/items/properties/content/anyOf/1/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err141]; -} -else { -vErrors.push(err141); -} -errors++; -} -} -} -else { -const err142 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf/1/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err142]; -} -else { -vErrors.push(err142); -} -errors++; -} -var _valid0 = _errs170 === errors; -valid23 = valid23 || _valid0; -} -if(!valid23){ -const err143 = {instancePath:instancePath+"/messages/" + i2+"/content",schemaPath:"#/properties/messages/items/properties/content/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"}; -if(vErrors === null){ -vErrors = [err143]; -} -else { -vErrors.push(err143); -} -errors++; -} -else { -errors = _errs167; -if(vErrors !== null){ -if(_errs167){ -vErrors.length = _errs167; -} -else { -vErrors = null; -} -} -} -} -if(data34.tool_calls !== undefined){ -let data85 = data34.tool_calls; -if((data85 !== null) && (!(Array.isArray(data85)))){ -const err144 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls",schemaPath:"#/properties/messages/items/properties/tool_calls/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.tool_calls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err144]; -} -else { -vErrors.push(err144); -} -errors++; -} -if(Array.isArray(data85)){ -const len7 = data85.length; -for(let i7=0; i7<len7; i7++){ -let data86 = data85[i7]; -if(data86 && typeof data86 == "object" && !Array.isArray(data86)){ -if(data86.id === undefined){ -const err145 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err145]; -} -else { -vErrors.push(err145); -} -errors++; -} -if(data86.type === undefined){ -const err146 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err146]; -} -else { -vErrors.push(err146); -} -errors++; -} -if(data86.function === undefined){ -const err147 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err147]; -} -else { -vErrors.push(err147); -} -errors++; -} -if(data86.id !== undefined){ -if(typeof data86.id !== "string"){ -const err148 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/id",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err148]; -} -else { -vErrors.push(err148); -} -errors++; -} -} -if(data86.type !== undefined){ -if(typeof data86.type !== "string"){ -const err149 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/type",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err149]; -} -else { -vErrors.push(err149); -} -errors++; -} -} -if(data86.function !== undefined){ -let data89 = data86.function; -if(data89 && typeof data89 == "object" && !Array.isArray(data89)){ -if(data89.name === undefined){ -const err150 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err150]; -} -else { -vErrors.push(err150); -} -errors++; -} -if(data89.arguments === undefined){ -const err151 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err151]; -} -else { -vErrors.push(err151); -} -errors++; -} -if(data89.name !== undefined){ -if(typeof data89.name !== "string"){ -const err152 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function/name",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err152]; -} -else { -vErrors.push(err152); -} -errors++; -} -} -if(data89.arguments !== undefined){ -if(typeof data89.arguments !== "string"){ -const err153 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function/arguments",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/properties/arguments/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err153]; -} -else { -vErrors.push(err153); -} -errors++; -} -} -} -else { -const err154 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/function",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err154]; -} -else { -vErrors.push(err154); -} -errors++; -} -} -if(data86.duration_ms !== undefined){ -let data92 = data86.duration_ms; -if(!((typeof data92 == "number") && (!(data92 % 1) && !isNaN(data92)))){ -const err155 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/duration_ms",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/duration_ms/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err155]; -} -else { -vErrors.push(err155); -} -errors++; -} -} -if(data86.exit_code !== undefined){ -let data93 = data86.exit_code; -if(!((typeof data93 == "number") && (!(data93 % 1) && !isNaN(data93)))){ -const err156 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7+"/exit_code",schemaPath:"#/properties/messages/items/properties/tool_calls/items/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err156]; -} -else { -vErrors.push(err156); -} -errors++; -} -} -} -else { -const err157 = {instancePath:instancePath+"/messages/" + i2+"/tool_calls/" + i7,schemaPath:"#/properties/messages/items/properties/tool_calls/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err157]; -} -else { -vErrors.push(err157); -} -errors++; -} -} -} -} -if(data34.tool_call_id !== undefined){ -if(typeof data34.tool_call_id !== "string"){ -const err158 = {instancePath:instancePath+"/messages/" + i2+"/tool_call_id",schemaPath:"#/properties/messages/items/properties/tool_call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err158]; -} -else { -vErrors.push(err158); -} -errors++; -} -} -if(data34.name !== undefined){ -if(typeof data34.name !== "string"){ -const err159 = {instancePath:instancePath+"/messages/" + i2+"/name",schemaPath:"#/properties/messages/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err159]; -} -else { -vErrors.push(err159); -} -errors++; -} -} -if(data34.authored !== undefined){ -if(typeof data34.authored !== "boolean"){ -const err160 = {instancePath:instancePath+"/messages/" + i2+"/authored",schemaPath:"#/properties/messages/items/properties/authored/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err160]; -} -else { -vErrors.push(err160); -} -errors++; -} -} -if(data34.sent_at !== undefined){ -let data97 = data34.sent_at; -if((data97 !== null) && (typeof data97 !== "string")){ -const err161 = {instancePath:instancePath+"/messages/" + i2+"/sent_at",schemaPath:"#/properties/messages/items/properties/sent_at/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.sent_at.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err161]; -} -else { -vErrors.push(err161); -} -errors++; -} -} -if(data34.usage !== undefined){ -let data98 = data34.usage; -if((data98 !== null) && (!(data98 && typeof data98 == "object" && !Array.isArray(data98)))){ -const err162 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err162]; -} -else { -vErrors.push(err162); -} -errors++; -} -if(data98 && typeof data98 == "object" && !Array.isArray(data98)){ -if(data98.prompt_tokens === undefined){ -const err163 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err163]; -} -else { -vErrors.push(err163); -} -errors++; -} -if(data98.completion_tokens === undefined){ -const err164 = {instancePath:instancePath+"/messages/" + i2+"/usage",schemaPath:"#/properties/messages/items/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err164]; -} -else { -vErrors.push(err164); -} -errors++; -} -if(data98.reported !== undefined){ -if(typeof data98.reported !== "boolean"){ -const err165 = {instancePath:instancePath+"/messages/" + i2+"/usage/reported",schemaPath:"#/properties/messages/items/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err165]; -} -else { -vErrors.push(err165); -} -errors++; -} -} -if(data98.cost !== undefined){ -let data100 = data98.cost; -if((data100 !== null) && (!(typeof data100 == "number"))){ -const err166 = {instancePath:instancePath+"/messages/" + i2+"/usage/cost",schemaPath:"#/properties/messages/items/properties/usage/properties/cost/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err166]; -} -else { -vErrors.push(err166); -} -errors++; -} -} -if(data98.prompt_tokens !== undefined){ -let data101 = data98.prompt_tokens; -if(!((typeof data101 == "number") && (!(data101 % 1) && !isNaN(data101)))){ -const err167 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err167]; -} -else { -vErrors.push(err167); -} -errors++; -} -} -if(data98.completion_tokens !== undefined){ -let data102 = data98.completion_tokens; -if(!((typeof data102 == "number") && (!(data102 % 1) && !isNaN(data102)))){ -const err168 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err168]; -} -else { -vErrors.push(err168); -} -errors++; -} -} -if(data98.prompt_tokens_details !== undefined){ -let data103 = data98.prompt_tokens_details; -if((data103 !== null) && (!(data103 && typeof data103 == "object" && !Array.isArray(data103)))){ -const err169 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err169]; -} -else { -vErrors.push(err169); -} -errors++; -} -if(data103 && typeof data103 == "object" && !Array.isArray(data103)){ -if(data103.cached_tokens === undefined){ -const err170 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err170]; -} -else { -vErrors.push(err170); -} -errors++; -} -if(data103.cached_tokens !== undefined){ -let data104 = data103.cached_tokens; -if(!((typeof data104 == "number") && (!(data104 % 1) && !isNaN(data104)))){ -const err171 = {instancePath:instancePath+"/messages/" + i2+"/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err171]; -} -else { -vErrors.push(err171); -} -errors++; -} -} -} -} -if(data98.completion_tokens_details !== undefined){ -let data105 = data98.completion_tokens_details; -if((data105 !== null) && (!(data105 && typeof data105 == "object" && !Array.isArray(data105)))){ -const err172 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema160.properties.messages.items.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err172]; -} -else { -vErrors.push(err172); -} -errors++; -} -if(data105 && typeof data105 == "object" && !Array.isArray(data105)){ -if(data105.reasoning_tokens === undefined){ -const err173 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err173]; -} -else { -vErrors.push(err173); -} -errors++; -} -if(data105.reasoning_tokens !== undefined){ -let data106 = data105.reasoning_tokens; -if(!((typeof data106 == "number") && (!(data106 % 1) && !isNaN(data106)))){ -const err174 = {instancePath:instancePath+"/messages/" + i2+"/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/messages/items/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err174]; -} -else { -vErrors.push(err174); -} -errors++; -} -} -} -} -} -} -if(data34.model !== undefined){ -if(typeof data34.model !== "string"){ -const err175 = {instancePath:instancePath+"/messages/" + i2+"/model",schemaPath:"#/properties/messages/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err175]; -} -else { -vErrors.push(err175); -} -errors++; -} -} -if(data34.rewound_from !== undefined){ -if(typeof data34.rewound_from !== "string"){ -const err176 = {instancePath:instancePath+"/messages/" + i2+"/rewound_from",schemaPath:"#/properties/messages/items/properties/rewound_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err176]; -} -else { -vErrors.push(err176); -} -errors++; -} -} -if(data34.call_id !== undefined){ -if(typeof data34.call_id !== "string"){ -const err177 = {instancePath:instancePath+"/messages/" + i2+"/call_id",schemaPath:"#/properties/messages/items/properties/call_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err177]; -} -else { -vErrors.push(err177); -} -errors++; -} -} -} -else { -const err178 = {instancePath:instancePath+"/messages/" + i2,schemaPath:"#/properties/messages/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err178]; -} -else { -vErrors.push(err178); -} -errors++; -} -} -} -} -if(data.presentation !== undefined){ -let data110 = data.presentation; -if((data110 !== null) && (!(Array.isArray(data110)))){ -const err179 = {instancePath:instancePath+"/presentation",schemaPath:"#/properties/presentation/type",keyword:"type",params:{type: schema160.properties.presentation.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err179]; -} -else { -vErrors.push(err179); -} -errors++; -} -if(Array.isArray(data110)){ -const len8 = data110.length; -for(let i8=0; i8<len8; i8++){ -let data111 = data110[i8]; -if(data111 && typeof data111 == "object" && !Array.isArray(data111)){ -if(data111.seq === undefined){ -const err180 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err180]; -} -else { -vErrors.push(err180); -} -errors++; -} -if(data111.kind === undefined){ -const err181 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err181]; -} -else { -vErrors.push(err181); -} -errors++; -} -if(data111.payload === undefined){ -const err182 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err182]; -} -else { -vErrors.push(err182); -} -errors++; -} -if(data111.seq !== undefined){ -let data112 = data111.seq; -if(typeof data112 === "string"){ -if(!pattern0.test(data112)){ -const err183 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err183]; -} -else { -vErrors.push(err183); -} -errors++; -} -if(!(formats0.validate(data112))){ -const err184 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err184]; -} -else { -vErrors.push(err184); -} -errors++; -} -} -else { -const err185 = {instancePath:instancePath+"/presentation/" + i8+"/seq",schemaPath:"#/properties/presentation/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err185]; -} -else { -vErrors.push(err185); -} -errors++; -} -} -if(data111.kind !== undefined){ -if(typeof data111.kind !== "string"){ -const err186 = {instancePath:instancePath+"/presentation/" + i8+"/kind",schemaPath:"#/properties/presentation/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err186]; -} -else { -vErrors.push(err186); -} -errors++; -} -} -} -else { -const err187 = {instancePath:instancePath+"/presentation/" + i8,schemaPath:"#/properties/presentation/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err187]; -} -else { -vErrors.push(err187); -} -errors++; -} -} -} -} -if(data.agent_presentations !== undefined){ -let data114 = data.agent_presentations; -if(data114 && typeof data114 == "object" && !Array.isArray(data114)){ -for(const key2 in data114){ -let data115 = data114[key2]; -if((data115 !== null) && (!(Array.isArray(data115)))){ -const err188 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1"),schemaPath:"#/properties/agent_presentations/additionalProperties/type",keyword:"type",params:{type: schema160.properties.agent_presentations.additionalProperties.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err188]; -} -else { -vErrors.push(err188); -} -errors++; -} -if(Array.isArray(data115)){ -const len9 = data115.length; -for(let i9=0; i9<len9; i9++){ -let data116 = data115[i9]; -if(data116 && typeof data116 == "object" && !Array.isArray(data116)){ -if(data116.seq === undefined){ -const err189 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err189]; -} -else { -vErrors.push(err189); -} -errors++; -} -if(data116.kind === undefined){ -const err190 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err190]; -} -else { -vErrors.push(err190); -} -errors++; -} -if(data116.payload === undefined){ -const err191 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err191]; -} -else { -vErrors.push(err191); -} -errors++; -} -if(data116.seq !== undefined){ -let data117 = data116.seq; -if(typeof data117 === "string"){ -if(!pattern0.test(data117)){ -const err192 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err192]; -} -else { -vErrors.push(err192); -} -errors++; -} -if(!(formats0.validate(data117))){ -const err193 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err193]; -} -else { -vErrors.push(err193); -} -errors++; -} -} -else { -const err194 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/seq",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err194]; -} -else { -vErrors.push(err194); -} -errors++; -} -} -if(data116.kind !== undefined){ -if(typeof data116.kind !== "string"){ -const err195 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9+"/kind",schemaPath:"#/properties/agent_presentations/additionalProperties/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err195]; -} -else { -vErrors.push(err195); -} -errors++; -} -} -} -else { -const err196 = {instancePath:instancePath+"/agent_presentations/" + key2.replace(/~/g, "~0").replace(/\//g, "~1")+"/" + i9,schemaPath:"#/properties/agent_presentations/additionalProperties/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err196]; -} -else { -vErrors.push(err196); -} -errors++; -} -} -} -} -} -else { -const err197 = {instancePath:instancePath+"/agent_presentations",schemaPath:"#/properties/agent_presentations/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err197]; -} -else { -vErrors.push(err197); -} -errors++; -} -} -if(data.agents !== undefined){ -let data119 = data.agents; -if((data119 !== null) && (!(Array.isArray(data119)))){ -const err198 = {instancePath:instancePath+"/agents",schemaPath:"#/properties/agents/type",keyword:"type",params:{type: schema160.properties.agents.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err198]; -} -else { -vErrors.push(err198); -} -errors++; -} -if(Array.isArray(data119)){ -const len10 = data119.length; -for(let i10=0; i10<len10; i10++){ -let data120 = data119[i10]; -if(data120 && typeof data120 == "object" && !Array.isArray(data120)){ -if(data120.execution_engine === undefined){ -const err199 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err199]; -} -else { -vErrors.push(err199); -} -errors++; -} -if(data120.id === undefined){ -const err200 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err200]; -} -else { -vErrors.push(err200); -} -errors++; -} -if(data120.root_id === undefined){ -const err201 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err201]; -} -else { -vErrors.push(err201); -} -errors++; -} -if(data120.parent_id === undefined){ -const err202 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "parent_id"},message:"must have required property '"+"parent_id"+"'"}; -if(vErrors === null){ -vErrors = [err202]; -} -else { -vErrors.push(err202); -} -errors++; -} -if(data120.name === undefined){ -const err203 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err203]; -} -else { -vErrors.push(err203); -} -errors++; -} -if(data120.model === undefined){ -const err204 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err204]; -} -else { -vErrors.push(err204); -} -errors++; -} -if(data120.provider === undefined){ -const err205 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err205]; -} -else { -vErrors.push(err205); -} -errors++; -} -if(data120.effort === undefined){ -const err206 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err206]; -} -else { -vErrors.push(err206); -} -errors++; -} -if(data120.cwd === undefined){ -const err207 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err207]; -} -else { -vErrors.push(err207); -} -errors++; -} -if(data120.report === undefined){ -const err208 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "report"},message:"must have required property '"+"report"+"'"}; -if(vErrors === null){ -vErrors = [err208]; -} -else { -vErrors.push(err208); -} -errors++; -} -if(data120.status === undefined){ -const err209 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err209]; -} -else { -vErrors.push(err209); -} -errors++; -} -if(data120.pending_mail === undefined){ -const err210 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "pending_mail"},message:"must have required property '"+"pending_mail"+"'"}; -if(vErrors === null){ -vErrors = [err210]; -} -else { -vErrors.push(err210); -} -errors++; -} -if(data120.lifecycle_phase === undefined){ -const err211 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "lifecycle_phase"},message:"must have required property '"+"lifecycle_phase"+"'"}; -if(vErrors === null){ -vErrors = [err211]; -} -else { -vErrors.push(err211); -} -errors++; -} -if(data120.blocking_reason === undefined){ -const err212 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "blocking_reason"},message:"must have required property '"+"blocking_reason"+"'"}; -if(vErrors === null){ -vErrors = [err212]; -} -else { -vErrors.push(err212); -} -errors++; -} -if(data120.terminal_cause === undefined){ -const err213 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "terminal_cause"},message:"must have required property '"+"terminal_cause"+"'"}; -if(vErrors === null){ -vErrors = [err213]; -} -else { -vErrors.push(err213); -} -errors++; -} -if(data120.allowed_controls === undefined){ -const err214 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/required",keyword:"required",params:{missingProperty: "allowed_controls"},message:"must have required property '"+"allowed_controls"+"'"}; -if(vErrors === null){ -vErrors = [err214]; -} -else { -vErrors.push(err214); -} -errors++; -} -if(data120.execution_engine !== undefined){ -if(typeof data120.execution_engine !== "string"){ -const err215 = {instancePath:instancePath+"/agents/" + i10+"/execution_engine",schemaPath:"#/properties/agents/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err215]; -} -else { -vErrors.push(err215); -} -errors++; -} -} -if(data120.last_turn !== undefined){ -let data122 = data120.last_turn; -if((data122 !== null) && (!(data122 && typeof data122 == "object" && !Array.isArray(data122)))){ -const err216 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err216]; -} -else { -vErrors.push(err216); -} -errors++; -} -if(data122 && typeof data122 == "object" && !Array.isArray(data122)){ -if(data122.status === undefined){ -const err217 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err217]; -} -else { -vErrors.push(err217); -} -errors++; -} -if(data122.event_seq === undefined){ -const err218 = {instancePath:instancePath+"/agents/" + i10+"/last_turn",schemaPath:"#/properties/agents/items/properties/last_turn/required",keyword:"required",params:{missingProperty: "event_seq"},message:"must have required property '"+"event_seq"+"'"}; -if(vErrors === null){ -vErrors = [err218]; -} -else { -vErrors.push(err218); -} -errors++; -} -if(data122.turn_id !== undefined){ -if(typeof data122.turn_id !== "string"){ -const err219 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/turn_id",schemaPath:"#/properties/agents/items/properties/last_turn/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err219]; -} -else { -vErrors.push(err219); -} -errors++; -} -} -if(data122.status !== undefined){ -if(typeof data122.status !== "string"){ -const err220 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/status",schemaPath:"#/properties/agents/items/properties/last_turn/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err220]; -} -else { -vErrors.push(err220); -} -errors++; -} -} -if(data122.started_at !== undefined){ -if(typeof data122.started_at !== "string"){ -const err221 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/started_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/started_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err221]; -} -else { -vErrors.push(err221); -} -errors++; -} -} -if(data122.finished_at !== undefined){ -if(typeof data122.finished_at !== "string"){ -const err222 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/finished_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/finished_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err222]; -} -else { -vErrors.push(err222); -} -errors++; -} -} -if(data122.event_seq !== undefined){ -let data127 = data122.event_seq; -if(typeof data127 === "string"){ -if(!pattern0.test(data127)){ -const err223 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err223]; -} -else { -vErrors.push(err223); -} -errors++; -} -if(!(formats0.validate(data127))){ -const err224 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err224]; -} -else { -vErrors.push(err224); -} -errors++; -} -} -else { -const err225 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/event_seq",schemaPath:"#/properties/agents/items/properties/last_turn/properties/event_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err225]; -} -else { -vErrors.push(err225); -} -errors++; -} -} -if(data122.error !== undefined){ -if(typeof data122.error !== "string"){ -const err226 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err226]; -} -else { -vErrors.push(err226); -} -errors++; -} -} -if(data122.error_truncated !== undefined){ -if(typeof data122.error_truncated !== "boolean"){ -const err227 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_truncated",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err227]; -} -else { -vErrors.push(err227); -} -errors++; -} -} -if(data122.error_details !== undefined){ -let data130 = data122.error_details; -if((data130 !== null) && (!(data130 && typeof data130 == "object" && !Array.isArray(data130)))){ -const err228 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err228]; -} -else { -vErrors.push(err228); -} -errors++; -} -if(data130 && typeof data130 == "object" && !Array.isArray(data130)){ -if(data130.reference_id === undefined){ -const err229 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err229]; -} -else { -vErrors.push(err229); -} -errors++; -} -if(data130.digest === undefined){ -const err230 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err230]; -} -else { -vErrors.push(err230); -} -errors++; -} -if(data130.size === undefined){ -const err231 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err231]; -} -else { -vErrors.push(err231); -} -errors++; -} -if(data130.media_type === undefined){ -const err232 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err232]; -} -else { -vErrors.push(err232); -} -errors++; -} -if(data130.source === undefined){ -const err233 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err233]; -} -else { -vErrors.push(err233); -} -errors++; -} -if(data130.text !== undefined){ -let data131 = data130.text; -if((data131 !== null) && (typeof data131 !== "string")){ -const err234 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/text",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/text/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err234]; -} -else { -vErrors.push(err234); -} -errors++; -} -} -if(data130.binary !== undefined){ -let data132 = data130.binary; -if((typeof data132 !== "string") && (data132 !== null)){ -const err235 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/binary",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/binary/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.last_turn.properties.error_details.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err235]; -} -else { -vErrors.push(err235); -} -errors++; -} -} -if(data130.reference_id !== undefined){ -if(typeof data130.reference_id !== "string"){ -const err236 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/reference_id",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err236]; -} -else { -vErrors.push(err236); -} -errors++; -} -} -if(data130.digest !== undefined){ -if(typeof data130.digest !== "string"){ -const err237 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/digest",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err237]; -} -else { -vErrors.push(err237); -} -errors++; -} -} -if(data130.size !== undefined){ -let data135 = data130.size; -if(typeof data135 === "string"){ -if(!pattern0.test(data135)){ -const err238 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err238]; -} -else { -vErrors.push(err238); -} -errors++; -} -if(!(formats0.validate(data135))){ -const err239 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err239]; -} -else { -vErrors.push(err239); -} -errors++; -} -} -else { -const err240 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/size",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err240]; -} -else { -vErrors.push(err240); -} -errors++; -} -} -if(data130.media_type !== undefined){ -if(typeof data130.media_type !== "string"){ -const err241 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/media_type",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err241]; -} -else { -vErrors.push(err241); -} -errors++; -} -} -if(data130.source !== undefined){ -if(typeof data130.source !== "string"){ -const err242 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/error_details/source",schemaPath:"#/properties/agents/items/properties/last_turn/properties/error_details/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err242]; -} -else { -vErrors.push(err242); -} -errors++; -} -} -} -} -if(data122.model_calls !== undefined){ -let data138 = data122.model_calls; -if(!((typeof data138 == "number") && (!(data138 % 1) && !isNaN(data138)))){ -const err243 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/model_calls",schemaPath:"#/properties/agents/items/properties/last_turn/properties/model_calls/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err243]; -} -else { -vErrors.push(err243); -} -errors++; -} -} -if(data122.compactions !== undefined){ -let data139 = data122.compactions; -if(!((typeof data139 == "number") && (!(data139 % 1) && !isNaN(data139)))){ -const err244 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/compactions",schemaPath:"#/properties/agents/items/properties/last_turn/properties/compactions/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err244]; -} -else { -vErrors.push(err244); -} -errors++; -} -} -if(data122.last_activity_at !== undefined){ -if(typeof data122.last_activity_at !== "string"){ -const err245 = {instancePath:instancePath+"/agents/" + i10+"/last_turn/last_activity_at",schemaPath:"#/properties/agents/items/properties/last_turn/properties/last_activity_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err245]; -} -else { -vErrors.push(err245); -} -errors++; -} -} -} -} -if(data120.id !== undefined){ -if(typeof data120.id !== "string"){ -const err246 = {instancePath:instancePath+"/agents/" + i10+"/id",schemaPath:"#/properties/agents/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err246]; -} -else { -vErrors.push(err246); -} -errors++; -} -} -if(data120.root_id !== undefined){ -if(typeof data120.root_id !== "string"){ -const err247 = {instancePath:instancePath+"/agents/" + i10+"/root_id",schemaPath:"#/properties/agents/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err247]; -} -else { -vErrors.push(err247); -} -errors++; -} -} -if(data120.parent_id !== undefined){ -if(typeof data120.parent_id !== "string"){ -const err248 = {instancePath:instancePath+"/agents/" + i10+"/parent_id",schemaPath:"#/properties/agents/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err248]; -} -else { -vErrors.push(err248); -} -errors++; -} -} -if(data120.name !== undefined){ -if(typeof data120.name !== "string"){ -const err249 = {instancePath:instancePath+"/agents/" + i10+"/name",schemaPath:"#/properties/agents/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err249]; -} -else { -vErrors.push(err249); -} -errors++; -} -} -if(data120.model !== undefined){ -if(typeof data120.model !== "string"){ -const err250 = {instancePath:instancePath+"/agents/" + i10+"/model",schemaPath:"#/properties/agents/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err250]; -} -else { -vErrors.push(err250); -} -errors++; -} -} -if(data120.provider !== undefined){ -if(typeof data120.provider !== "string"){ -const err251 = {instancePath:instancePath+"/agents/" + i10+"/provider",schemaPath:"#/properties/agents/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err251]; -} -else { -vErrors.push(err251); -} -errors++; -} -} -if(data120.effort !== undefined){ -if(typeof data120.effort !== "string"){ -const err252 = {instancePath:instancePath+"/agents/" + i10+"/effort",schemaPath:"#/properties/agents/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err252]; -} -else { -vErrors.push(err252); -} -errors++; -} -} -if(data120.cwd !== undefined){ -if(typeof data120.cwd !== "string"){ -const err253 = {instancePath:instancePath+"/agents/" + i10+"/cwd",schemaPath:"#/properties/agents/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err253]; -} -else { -vErrors.push(err253); -} -errors++; -} -} -if(data120.report !== undefined){ -if(typeof data120.report !== "string"){ -const err254 = {instancePath:instancePath+"/agents/" + i10+"/report",schemaPath:"#/properties/agents/items/properties/report/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err254]; -} -else { -vErrors.push(err254); -} -errors++; -} -} -if(data120.status !== undefined){ -if(typeof data120.status !== "string"){ -const err255 = {instancePath:instancePath+"/agents/" + i10+"/status",schemaPath:"#/properties/agents/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err255]; -} -else { -vErrors.push(err255); -} -errors++; -} -} -if(data120.pending_mail !== undefined){ -let data151 = data120.pending_mail; -if(!((typeof data151 == "number") && (!(data151 % 1) && !isNaN(data151)))){ -const err256 = {instancePath:instancePath+"/agents/" + i10+"/pending_mail",schemaPath:"#/properties/agents/items/properties/pending_mail/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err256]; -} -else { -vErrors.push(err256); -} -errors++; -} -} -if(data120.lifecycle_phase !== undefined){ -if(typeof data120.lifecycle_phase !== "string"){ -const err257 = {instancePath:instancePath+"/agents/" + i10+"/lifecycle_phase",schemaPath:"#/properties/agents/items/properties/lifecycle_phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err257]; -} -else { -vErrors.push(err257); -} -errors++; -} -} -if(data120.blocking_reason !== undefined){ -if(typeof data120.blocking_reason !== "string"){ -const err258 = {instancePath:instancePath+"/agents/" + i10+"/blocking_reason",schemaPath:"#/properties/agents/items/properties/blocking_reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err258]; -} -else { -vErrors.push(err258); -} -errors++; -} -} -if(data120.terminal_cause !== undefined){ -if(typeof data120.terminal_cause !== "string"){ -const err259 = {instancePath:instancePath+"/agents/" + i10+"/terminal_cause",schemaPath:"#/properties/agents/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err259]; -} -else { -vErrors.push(err259); -} -errors++; -} -} -if(data120.allowed_controls !== undefined){ -let data155 = data120.allowed_controls; -if((data155 !== null) && (!(Array.isArray(data155)))){ -const err260 = {instancePath:instancePath+"/agents/" + i10+"/allowed_controls",schemaPath:"#/properties/agents/items/properties/allowed_controls/type",keyword:"type",params:{type: schema160.properties.agents.items.properties.allowed_controls.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err260]; -} -else { -vErrors.push(err260); -} -errors++; -} -if(Array.isArray(data155)){ -const len11 = data155.length; -for(let i11=0; i11<len11; i11++){ -if(typeof data155[i11] !== "string"){ -const err261 = {instancePath:instancePath+"/agents/" + i10+"/allowed_controls/" + i11,schemaPath:"#/properties/agents/items/properties/allowed_controls/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err261]; -} -else { -vErrors.push(err261); -} -errors++; -} -} -} -} -} -else { -const err262 = {instancePath:instancePath+"/agents/" + i10,schemaPath:"#/properties/agents/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err262]; -} -else { -vErrors.push(err262); -} -errors++; -} -} -} -} -if(data.inbox !== undefined){ -let data157 = data.inbox; -if((data157 !== null) && (!(Array.isArray(data157)))){ -const err263 = {instancePath:instancePath+"/inbox",schemaPath:"#/properties/inbox/type",keyword:"type",params:{type: schema160.properties.inbox.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err263]; -} -else { -vErrors.push(err263); -} -errors++; -} -if(Array.isArray(data157)){ -const len12 = data157.length; -for(let i12=0; i12<len12; i12++){ -let data158 = data157[i12]; -if(data158 && typeof data158 == "object" && !Array.isArray(data158)){ -if(data158.root_id === undefined){ -const err264 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err264]; -} -else { -vErrors.push(err264); -} -errors++; -} -if(data158.agent_id === undefined){ -const err265 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err265]; -} -else { -vErrors.push(err265); -} -errors++; -} -if(data158.seq === undefined){ -const err266 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "seq"},message:"must have required property '"+"seq"+"'"}; -if(vErrors === null){ -vErrors = [err266]; -} -else { -vErrors.push(err266); -} -errors++; -} -if(data158.kind === undefined){ -const err267 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err267]; -} -else { -vErrors.push(err267); -} -errors++; -} -if(data158.status === undefined){ -const err268 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err268]; -} -else { -vErrors.push(err268); -} -errors++; -} -if(data158.payload === undefined){ -const err269 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err269]; -} -else { -vErrors.push(err269); -} -errors++; -} -if(data158.delivery_seq !== undefined){ -let data159 = data158.delivery_seq; -if(typeof data159 === "string"){ -if(!pattern0.test(data159)){ -const err270 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err270]; -} -else { -vErrors.push(err270); -} -errors++; -} -if(!(formats0.validate(data159))){ -const err271 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err271]; -} -else { -vErrors.push(err271); -} -errors++; -} -} -else { -const err272 = {instancePath:instancePath+"/inbox/" + i12+"/delivery_seq",schemaPath:"#/properties/inbox/items/properties/delivery_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err272]; -} -else { -vErrors.push(err272); -} -errors++; -} -} -if(data158.origin !== undefined){ -if(typeof data158.origin !== "string"){ -const err273 = {instancePath:instancePath+"/inbox/" + i12+"/origin",schemaPath:"#/properties/inbox/items/properties/origin/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err273]; -} -else { -vErrors.push(err273); -} -errors++; -} -} -if(data158.command_client_id !== undefined){ -if(typeof data158.command_client_id !== "string"){ -const err274 = {instancePath:instancePath+"/inbox/" + i12+"/command_client_id",schemaPath:"#/properties/inbox/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err274]; -} -else { -vErrors.push(err274); -} -errors++; -} -} -if(data158.command_id !== undefined){ -if(typeof data158.command_id !== "string"){ -const err275 = {instancePath:instancePath+"/inbox/" + i12+"/command_id",schemaPath:"#/properties/inbox/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err275]; -} -else { -vErrors.push(err275); -} -errors++; -} -} -if(data158.steer_turn_id !== undefined){ -if(typeof data158.steer_turn_id !== "string"){ -const err276 = {instancePath:instancePath+"/inbox/" + i12+"/steer_turn_id",schemaPath:"#/properties/inbox/items/properties/steer_turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err276]; -} -else { -vErrors.push(err276); -} -errors++; -} -} -if(data158.preview !== undefined){ -let data164 = data158.preview; -if((data164 !== null) && (!(data164 && typeof data164 == "object" && !Array.isArray(data164)))){ -const err277 = {instancePath:instancePath+"/inbox/" + i12+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err277]; -} -else { -vErrors.push(err277); -} -errors++; -} -if(data164 && typeof data164 == "object" && !Array.isArray(data164)){ -if(data164.text === undefined){ -const err278 = {instancePath:instancePath+"/inbox/" + i12+"/preview",schemaPath:"#/properties/inbox/items/properties/preview/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err278]; -} -else { -vErrors.push(err278); -} -errors++; -} -if(data164.design_context !== undefined){ -let data165 = data164.design_context; -if((data165 !== null) && (!(data165 && typeof data165 == "object" && !Array.isArray(data165)))){ -const err279 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err279]; -} -else { -vErrors.push(err279); -} -errors++; -} -if(data165 && typeof data165 == "object" && !Array.isArray(data165)){ -if(data165.context_attachment_id === undefined){ -const err280 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err280]; -} -else { -vErrors.push(err280); -} -errors++; -} -if(data165.elements === undefined){ -const err281 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err281]; -} -else { -vErrors.push(err281); -} -errors++; -} -if(data165.element_count === undefined){ -const err282 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err282]; -} -else { -vErrors.push(err282); -} -errors++; -} -if(data165.context_attachment_id !== undefined){ -if(typeof data165.context_attachment_id !== "string"){ -const err283 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/context_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err283]; -} -else { -vErrors.push(err283); -} -errors++; -} -} -if(data165.screenshot_attachment_id !== undefined){ -if(typeof data165.screenshot_attachment_id !== "string"){ -const err284 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/screenshot_attachment_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err284]; -} -else { -vErrors.push(err284); -} -errors++; -} -} -if(data165.elements !== undefined){ -let data168 = data165.elements; -if((data168 !== null) && (!(Array.isArray(data168)))){ -const err285 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err285]; -} -else { -vErrors.push(err285); -} -errors++; -} -if(Array.isArray(data168)){ -const len13 = data168.length; -for(let i13=0; i13<len13; i13++){ -let data169 = data168[i13]; -if(data169 && typeof data169 == "object" && !Array.isArray(data169)){ -if(data169.label === undefined){ -const err286 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err286]; -} -else { -vErrors.push(err286); -} -errors++; -} -if(data169.label !== undefined){ -if(typeof data169.label !== "string"){ -const err287 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13+"/label",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err287]; -} -else { -vErrors.push(err287); -} -errors++; -} -} -if(data169.selector !== undefined){ -if(typeof data169.selector !== "string"){ -const err288 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13+"/selector",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err288]; -} -else { -vErrors.push(err288); -} -errors++; -} -} -} -else { -const err289 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/elements/" + i13,schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err289]; -} -else { -vErrors.push(err289); -} -errors++; -} -} -} -} -if(data165.element_count !== undefined){ -let data172 = data165.element_count; -if(!((typeof data172 == "number") && (!(data172 % 1) && !isNaN(data172)))){ -const err290 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/element_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err290]; -} -else { -vErrors.push(err290); -} -errors++; -} -} -if(data165.page_url !== undefined){ -if(typeof data165.page_url !== "string"){ -const err291 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/page_url",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err291]; -} -else { -vErrors.push(err291); -} -errors++; -} -} -if(data165.page_title !== undefined){ -if(typeof data165.page_title !== "string"){ -const err292 = {instancePath:instancePath+"/inbox/" + i12+"/preview/design_context/page_title",schemaPath:"#/properties/inbox/items/properties/preview/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err292]; -} -else { -vErrors.push(err292); -} -errors++; -} -} -} -} -if(data164.text !== undefined){ -if(typeof data164.text !== "string"){ -const err293 = {instancePath:instancePath+"/inbox/" + i12+"/preview/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err293]; -} -else { -vErrors.push(err293); -} -errors++; -} -} -if(data164.truncated !== undefined){ -if(typeof data164.truncated !== "boolean"){ -const err294 = {instancePath:instancePath+"/inbox/" + i12+"/preview/truncated",schemaPath:"#/properties/inbox/items/properties/preview/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err294]; -} -else { -vErrors.push(err294); -} -errors++; -} -} -if(data164.attachments !== undefined){ -let data177 = data164.attachments; -if((data177 !== null) && (!(Array.isArray(data177)))){ -const err295 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err295]; -} -else { -vErrors.push(err295); -} -errors++; -} -if(Array.isArray(data177)){ -const len14 = data177.length; -for(let i14=0; i14<len14; i14++){ -let data178 = data177[i14]; -if(data178 && typeof data178 == "object" && !Array.isArray(data178)){ -if(data178.kind === undefined){ -const err296 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err296]; -} -else { -vErrors.push(err296); -} -errors++; -} -if(data178.content === undefined){ -const err297 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err297]; -} -else { -vErrors.push(err297); -} -errors++; -} -if(data178.kind !== undefined){ -if(typeof data178.kind !== "string"){ -const err298 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/kind",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err298]; -} -else { -vErrors.push(err298); -} -errors++; -} -} -if(data178.name !== undefined){ -if(typeof data178.name !== "string"){ -const err299 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/name",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err299]; -} -else { -vErrors.push(err299); -} -errors++; -} -} -if(data178.content !== undefined){ -let data181 = data178.content; -if(data181 && typeof data181 == "object" && !Array.isArray(data181)){ -if(data181.reference_id === undefined){ -const err300 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err300]; -} -else { -vErrors.push(err300); -} -errors++; -} -if(data181.digest === undefined){ -const err301 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err301]; -} -else { -vErrors.push(err301); -} -errors++; -} -if(data181.size === undefined){ -const err302 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err302]; -} -else { -vErrors.push(err302); -} -errors++; -} -if(data181.media_type === undefined){ -const err303 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err303]; -} -else { -vErrors.push(err303); -} -errors++; -} -if(data181.source === undefined){ -const err304 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err304]; -} -else { -vErrors.push(err304); -} -errors++; -} -if(data181.text !== undefined){ -let data182 = data181.text; -if((data182 !== null) && (typeof data182 !== "string")){ -const err305 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/text",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/text/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err305]; -} -else { -vErrors.push(err305); -} -errors++; -} -} -if(data181.binary !== undefined){ -let data183 = data181.binary; -if((typeof data183 !== "string") && (data183 !== null)){ -const err306 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/binary",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/binary/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.preview.properties.attachments.items.properties.content.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err306]; -} -else { -vErrors.push(err306); -} -errors++; -} -} -if(data181.reference_id !== undefined){ -if(typeof data181.reference_id !== "string"){ -const err307 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/reference_id",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err307]; -} -else { -vErrors.push(err307); -} -errors++; -} -} -if(data181.digest !== undefined){ -if(typeof data181.digest !== "string"){ -const err308 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/digest",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err308]; -} -else { -vErrors.push(err308); -} -errors++; -} -} -if(data181.size !== undefined){ -let data186 = data181.size; -if(typeof data186 === "string"){ -if(!pattern0.test(data186)){ -const err309 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err309]; -} -else { -vErrors.push(err309); -} -errors++; -} -if(!(formats0.validate(data186))){ -const err310 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err310]; -} -else { -vErrors.push(err310); -} -errors++; -} -} -else { -const err311 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/size",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err311]; -} -else { -vErrors.push(err311); -} -errors++; -} -} -if(data181.media_type !== undefined){ -if(typeof data181.media_type !== "string"){ -const err312 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/media_type",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err312]; -} -else { -vErrors.push(err312); -} -errors++; -} -} -if(data181.source !== undefined){ -if(typeof data181.source !== "string"){ -const err313 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content/source",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err313]; -} -else { -vErrors.push(err313); -} -errors++; -} -} -} -else { -const err314 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14+"/content",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err314]; -} -else { -vErrors.push(err314); -} -errors++; -} -} -} -else { -const err315 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachments/" + i14,schemaPath:"#/properties/inbox/items/properties/preview/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err315]; -} -else { -vErrors.push(err315); -} -errors++; -} -} -} -} -if(data164.attachment_count !== undefined){ -let data189 = data164.attachment_count; -if(!((typeof data189 == "number") && (!(data189 % 1) && !isNaN(data189)))){ -const err316 = {instancePath:instancePath+"/inbox/" + i12+"/preview/attachment_count",schemaPath:"#/properties/inbox/items/properties/preview/properties/attachment_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err316]; -} -else { -vErrors.push(err316); -} -errors++; -} -} -} -} -if(data158.root_id !== undefined){ -if(typeof data158.root_id !== "string"){ -const err317 = {instancePath:instancePath+"/inbox/" + i12+"/root_id",schemaPath:"#/properties/inbox/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err317]; -} -else { -vErrors.push(err317); -} -errors++; -} -} -if(data158.agent_id !== undefined){ -if(typeof data158.agent_id !== "string"){ -const err318 = {instancePath:instancePath+"/inbox/" + i12+"/agent_id",schemaPath:"#/properties/inbox/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err318]; -} -else { -vErrors.push(err318); -} -errors++; -} -} -if(data158.seq !== undefined){ -let data192 = data158.seq; -if(typeof data192 === "string"){ -if(!pattern0.test(data192)){ -const err319 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err319]; -} -else { -vErrors.push(err319); -} -errors++; -} -if(!(formats0.validate(data192))){ -const err320 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err320]; -} -else { -vErrors.push(err320); -} -errors++; -} -} -else { -const err321 = {instancePath:instancePath+"/inbox/" + i12+"/seq",schemaPath:"#/properties/inbox/items/properties/seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err321]; -} -else { -vErrors.push(err321); -} -errors++; -} -} -if(data158.kind !== undefined){ -if(typeof data158.kind !== "string"){ -const err322 = {instancePath:instancePath+"/inbox/" + i12+"/kind",schemaPath:"#/properties/inbox/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err322]; -} -else { -vErrors.push(err322); -} -errors++; -} -} -if(data158.status !== undefined){ -if(typeof data158.status !== "string"){ -const err323 = {instancePath:instancePath+"/inbox/" + i12+"/status",schemaPath:"#/properties/inbox/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err323]; -} -else { -vErrors.push(err323); -} -errors++; -} -} -if(data158.payload !== undefined){ -let data195 = data158.payload; -if(data195 && typeof data195 == "object" && !Array.isArray(data195)){ -if(data195.reference_id === undefined){ -const err324 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err324]; -} -else { -vErrors.push(err324); -} -errors++; -} -if(data195.digest === undefined){ -const err325 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err325]; -} -else { -vErrors.push(err325); -} -errors++; -} -if(data195.size === undefined){ -const err326 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err326]; -} -else { -vErrors.push(err326); -} -errors++; -} -if(data195.media_type === undefined){ -const err327 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err327]; -} -else { -vErrors.push(err327); -} -errors++; -} -if(data195.source === undefined){ -const err328 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err328]; -} -else { -vErrors.push(err328); -} -errors++; -} -if(data195.text !== undefined){ -let data196 = data195.text; -if((data196 !== null) && (typeof data196 !== "string")){ -const err329 = {instancePath:instancePath+"/inbox/" + i12+"/payload/text",schemaPath:"#/properties/inbox/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err329]; -} -else { -vErrors.push(err329); -} -errors++; -} -} -if(data195.binary !== undefined){ -let data197 = data195.binary; -if((typeof data197 !== "string") && (data197 !== null)){ -const err330 = {instancePath:instancePath+"/inbox/" + i12+"/payload/binary",schemaPath:"#/properties/inbox/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema160.properties.inbox.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err330]; -} -else { -vErrors.push(err330); -} -errors++; -} -} -if(data195.reference_id !== undefined){ -if(typeof data195.reference_id !== "string"){ -const err331 = {instancePath:instancePath+"/inbox/" + i12+"/payload/reference_id",schemaPath:"#/properties/inbox/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err331]; -} -else { -vErrors.push(err331); -} -errors++; -} -} -if(data195.digest !== undefined){ -if(typeof data195.digest !== "string"){ -const err332 = {instancePath:instancePath+"/inbox/" + i12+"/payload/digest",schemaPath:"#/properties/inbox/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err332]; -} -else { -vErrors.push(err332); -} -errors++; -} -} -if(data195.size !== undefined){ -let data200 = data195.size; -if(typeof data200 === "string"){ -if(!pattern0.test(data200)){ -const err333 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err333]; -} -else { -vErrors.push(err333); -} -errors++; -} -if(!(formats0.validate(data200))){ -const err334 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err334]; -} -else { -vErrors.push(err334); -} -errors++; -} -} -else { -const err335 = {instancePath:instancePath+"/inbox/" + i12+"/payload/size",schemaPath:"#/properties/inbox/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err335]; -} -else { -vErrors.push(err335); -} -errors++; -} -} -if(data195.media_type !== undefined){ -if(typeof data195.media_type !== "string"){ -const err336 = {instancePath:instancePath+"/inbox/" + i12+"/payload/media_type",schemaPath:"#/properties/inbox/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err336]; -} -else { -vErrors.push(err336); -} -errors++; -} -} -if(data195.source !== undefined){ -if(typeof data195.source !== "string"){ -const err337 = {instancePath:instancePath+"/inbox/" + i12+"/payload/source",schemaPath:"#/properties/inbox/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err337]; -} -else { -vErrors.push(err337); -} -errors++; -} -} -} -else { -const err338 = {instancePath:instancePath+"/inbox/" + i12+"/payload",schemaPath:"#/properties/inbox/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err338]; -} -else { -vErrors.push(err338); -} -errors++; -} -} -} -else { -const err339 = {instancePath:instancePath+"/inbox/" + i12,schemaPath:"#/properties/inbox/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err339]; -} -else { -vErrors.push(err339); -} -errors++; -} -} -} -} -if(data.blackboard !== undefined){ -let data203 = data.blackboard; -if((data203 !== null) && (!(Array.isArray(data203)))){ -const err340 = {instancePath:instancePath+"/blackboard",schemaPath:"#/properties/blackboard/type",keyword:"type",params:{type: schema160.properties.blackboard.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err340]; -} -else { -vErrors.push(err340); -} -errors++; -} -if(Array.isArray(data203)){ -const len15 = data203.length; -for(let i15=0; i15<len15; i15++){ -let data204 = data203[i15]; -if(data204 && typeof data204 == "object" && !Array.isArray(data204)){ -if(data204.key === undefined){ -const err341 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "key"},message:"must have required property '"+"key"+"'"}; -if(vErrors === null){ -vErrors = [err341]; -} -else { -vErrors.push(err341); -} -errors++; -} -if(data204.version === undefined){ -const err342 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "version"},message:"must have required property '"+"version"+"'"}; -if(vErrors === null){ -vErrors = [err342]; -} -else { -vErrors.push(err342); -} -errors++; -} -if(data204.author_agent_id === undefined){ -const err343 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "author_agent_id"},message:"must have required property '"+"author_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err343]; -} -else { -vErrors.push(err343); -} -errors++; -} -if(data204.payload === undefined){ -const err344 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/required",keyword:"required",params:{missingProperty: "payload"},message:"must have required property '"+"payload"+"'"}; -if(vErrors === null){ -vErrors = [err344]; -} -else { -vErrors.push(err344); -} -errors++; -} -if(data204.key !== undefined){ -if(typeof data204.key !== "string"){ -const err345 = {instancePath:instancePath+"/blackboard/" + i15+"/key",schemaPath:"#/properties/blackboard/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err345]; -} -else { -vErrors.push(err345); -} -errors++; -} -} -if(data204.version !== undefined){ -let data206 = data204.version; -if(typeof data206 === "string"){ -if(!pattern0.test(data206)){ -const err346 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err346]; -} -else { -vErrors.push(err346); -} -errors++; -} -if(!(formats0.validate(data206))){ -const err347 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err347]; -} -else { -vErrors.push(err347); -} -errors++; -} -} -else { -const err348 = {instancePath:instancePath+"/blackboard/" + i15+"/version",schemaPath:"#/properties/blackboard/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err348]; -} -else { -vErrors.push(err348); -} -errors++; -} -} -if(data204.author_agent_id !== undefined){ -if(typeof data204.author_agent_id !== "string"){ -const err349 = {instancePath:instancePath+"/blackboard/" + i15+"/author_agent_id",schemaPath:"#/properties/blackboard/items/properties/author_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err349]; -} -else { -vErrors.push(err349); -} -errors++; -} -} -if(data204.payload !== undefined){ -let data208 = data204.payload; -if(data208 && typeof data208 == "object" && !Array.isArray(data208)){ -if(data208.reference_id === undefined){ -const err350 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err350]; -} -else { -vErrors.push(err350); -} -errors++; -} -if(data208.digest === undefined){ -const err351 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err351]; -} -else { -vErrors.push(err351); -} -errors++; -} -if(data208.size === undefined){ -const err352 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err352]; -} -else { -vErrors.push(err352); -} -errors++; -} -if(data208.media_type === undefined){ -const err353 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "media_type"},message:"must have required property '"+"media_type"+"'"}; -if(vErrors === null){ -vErrors = [err353]; -} -else { -vErrors.push(err353); -} -errors++; -} -if(data208.source === undefined){ -const err354 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/required",keyword:"required",params:{missingProperty: "source"},message:"must have required property '"+"source"+"'"}; -if(vErrors === null){ -vErrors = [err354]; -} -else { -vErrors.push(err354); -} -errors++; -} -if(data208.text !== undefined){ -let data209 = data208.text; -if((data209 !== null) && (typeof data209 !== "string")){ -const err355 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/text",schemaPath:"#/properties/blackboard/items/properties/payload/properties/text/type",keyword:"type",params:{type: schema160.properties.blackboard.items.properties.payload.properties.text.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err355]; -} -else { -vErrors.push(err355); -} -errors++; -} -} -if(data208.binary !== undefined){ -let data210 = data208.binary; -if((typeof data210 !== "string") && (data210 !== null)){ -const err356 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/binary",schemaPath:"#/properties/blackboard/items/properties/payload/properties/binary/type",keyword:"type",params:{type: schema160.properties.blackboard.items.properties.payload.properties.binary.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err356]; -} -else { -vErrors.push(err356); -} -errors++; -} -} -if(data208.reference_id !== undefined){ -if(typeof data208.reference_id !== "string"){ -const err357 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/reference_id",schemaPath:"#/properties/blackboard/items/properties/payload/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err357]; -} -else { -vErrors.push(err357); -} -errors++; -} -} -if(data208.digest !== undefined){ -if(typeof data208.digest !== "string"){ -const err358 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/digest",schemaPath:"#/properties/blackboard/items/properties/payload/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err358]; -} -else { -vErrors.push(err358); -} -errors++; -} -} -if(data208.size !== undefined){ -let data213 = data208.size; -if(typeof data213 === "string"){ -if(!pattern0.test(data213)){ -const err359 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err359]; -} -else { -vErrors.push(err359); -} -errors++; -} -if(!(formats0.validate(data213))){ -const err360 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err360]; -} -else { -vErrors.push(err360); -} -errors++; -} -} -else { -const err361 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/size",schemaPath:"#/properties/blackboard/items/properties/payload/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err361]; -} -else { -vErrors.push(err361); -} -errors++; -} -} -if(data208.media_type !== undefined){ -if(typeof data208.media_type !== "string"){ -const err362 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/media_type",schemaPath:"#/properties/blackboard/items/properties/payload/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err362]; -} -else { -vErrors.push(err362); -} -errors++; -} -} -if(data208.source !== undefined){ -if(typeof data208.source !== "string"){ -const err363 = {instancePath:instancePath+"/blackboard/" + i15+"/payload/source",schemaPath:"#/properties/blackboard/items/properties/payload/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err363]; -} -else { -vErrors.push(err363); -} -errors++; -} -} -} -else { -const err364 = {instancePath:instancePath+"/blackboard/" + i15+"/payload",schemaPath:"#/properties/blackboard/items/properties/payload/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err364]; -} -else { -vErrors.push(err364); -} -errors++; -} -} -} -else { -const err365 = {instancePath:instancePath+"/blackboard/" + i15,schemaPath:"#/properties/blackboard/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err365]; -} -else { -vErrors.push(err365); -} -errors++; -} -} -} -} -if(data.budgets !== undefined){ -let data216 = data.budgets; -if((data216 !== null) && (!(Array.isArray(data216)))){ -const err366 = {instancePath:instancePath+"/budgets",schemaPath:"#/properties/budgets/type",keyword:"type",params:{type: schema160.properties.budgets.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err366]; -} -else { -vErrors.push(err366); -} -errors++; -} -if(Array.isArray(data216)){ -const len16 = data216.length; -for(let i16=0; i16<len16; i16++){ -let data217 = data216[i16]; -if(data217 && typeof data217 == "object" && !Array.isArray(data217)){ -if(data217.agent_id === undefined){ -const err367 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err367]; -} -else { -vErrors.push(err367); -} -errors++; -} -if(data217.state === undefined){ -const err368 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/required",keyword:"required",params:{missingProperty: "state"},message:"must have required property '"+"state"+"'"}; -if(vErrors === null){ -vErrors = [err368]; -} -else { -vErrors.push(err368); -} -errors++; -} -if(data217.agent_id !== undefined){ -if(typeof data217.agent_id !== "string"){ -const err369 = {instancePath:instancePath+"/budgets/" + i16+"/agent_id",schemaPath:"#/properties/budgets/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err369]; -} -else { -vErrors.push(err369); -} -errors++; -} -} -if(data217.state !== undefined){ -let data219 = data217.state; -if(data219 && typeof data219 == "object" && !Array.isArray(data219)){ -if(data219.kind === undefined){ -const err370 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err370]; -} -else { -vErrors.push(err370); -} -errors++; -} -if(data219.limit === undefined){ -const err371 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err371]; -} -else { -vErrors.push(err371); -} -errors++; -} -if(data219.used === undefined){ -const err372 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err372]; -} -else { -vErrors.push(err372); -} -errors++; -} -if(data219.reserved === undefined){ -const err373 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "reserved"},message:"must have required property '"+"reserved"+"'"}; -if(vErrors === null){ -vErrors = [err373]; -} -else { -vErrors.push(err373); -} -errors++; -} -if(data219.remaining === undefined){ -const err374 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "remaining"},message:"must have required property '"+"remaining"+"'"}; -if(vErrors === null){ -vErrors = [err374]; -} -else { -vErrors.push(err374); -} -errors++; -} -if(data219.uncertain === undefined){ -const err375 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "uncertain"},message:"must have required property '"+"uncertain"+"'"}; -if(vErrors === null){ -vErrors = [err375]; -} -else { -vErrors.push(err375); -} -errors++; -} -if(data219.incomplete === undefined){ -const err376 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/required",keyword:"required",params:{missingProperty: "incomplete"},message:"must have required property '"+"incomplete"+"'"}; -if(vErrors === null){ -vErrors = [err376]; -} -else { -vErrors.push(err376); -} -errors++; -} -if(data219.kind !== undefined){ -if(typeof data219.kind !== "string"){ -const err377 = {instancePath:instancePath+"/budgets/" + i16+"/state/kind",schemaPath:"#/properties/budgets/items/properties/state/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err377]; -} -else { -vErrors.push(err377); -} -errors++; -} -} -if(data219.limit !== undefined){ -let data221 = data219.limit; -if((typeof data221 !== "string") && (data221 !== null)){ -const err378 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/type",keyword:"type",params:{type: schema160.properties.budgets.items.properties.state.properties.limit.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err378]; -} -else { -vErrors.push(err378); -} -errors++; -} -if(typeof data221 === "string"){ -if(!pattern0.test(data221)){ -const err379 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err379]; -} -else { -vErrors.push(err379); -} -errors++; -} -if(!(formats0.validate(data221))){ -const err380 = {instancePath:instancePath+"/budgets/" + i16+"/state/limit",schemaPath:"#/properties/budgets/items/properties/state/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err380]; -} -else { -vErrors.push(err380); -} -errors++; -} -} -} -if(data219.used !== undefined){ -let data222 = data219.used; -if(typeof data222 === "string"){ -if(!pattern0.test(data222)){ -const err381 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err381]; -} -else { -vErrors.push(err381); -} -errors++; -} -if(!(formats0.validate(data222))){ -const err382 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err382]; -} -else { -vErrors.push(err382); -} -errors++; -} -} -else { -const err383 = {instancePath:instancePath+"/budgets/" + i16+"/state/used",schemaPath:"#/properties/budgets/items/properties/state/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err383]; -} -else { -vErrors.push(err383); -} -errors++; -} -} -if(data219.reserved !== undefined){ -let data223 = data219.reserved; -if(typeof data223 === "string"){ -if(!pattern0.test(data223)){ -const err384 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err384]; -} -else { -vErrors.push(err384); -} -errors++; -} -if(!(formats0.validate(data223))){ -const err385 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err385]; -} -else { -vErrors.push(err385); -} -errors++; -} -} -else { -const err386 = {instancePath:instancePath+"/budgets/" + i16+"/state/reserved",schemaPath:"#/properties/budgets/items/properties/state/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err386]; -} -else { -vErrors.push(err386); -} -errors++; -} -} -if(data219.remaining !== undefined){ -let data224 = data219.remaining; -if((typeof data224 !== "string") && (data224 !== null)){ -const err387 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/type",keyword:"type",params:{type: schema160.properties.budgets.items.properties.state.properties.remaining.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err387]; -} -else { -vErrors.push(err387); -} -errors++; -} -if(typeof data224 === "string"){ -if(!pattern0.test(data224)){ -const err388 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err388]; -} -else { -vErrors.push(err388); -} -errors++; -} -if(!(formats0.validate(data224))){ -const err389 = {instancePath:instancePath+"/budgets/" + i16+"/state/remaining",schemaPath:"#/properties/budgets/items/properties/state/properties/remaining/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err389]; -} -else { -vErrors.push(err389); -} -errors++; -} -} -} -if(data219.uncertain !== undefined){ -let data225 = data219.uncertain; -if(typeof data225 === "string"){ -if(!pattern0.test(data225)){ -const err390 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err390]; -} -else { -vErrors.push(err390); -} -errors++; -} -if(!(formats0.validate(data225))){ -const err391 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err391]; -} -else { -vErrors.push(err391); -} -errors++; -} -} -else { -const err392 = {instancePath:instancePath+"/budgets/" + i16+"/state/uncertain",schemaPath:"#/properties/budgets/items/properties/state/properties/uncertain/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err392]; -} -else { -vErrors.push(err392); -} -errors++; -} -} -if(data219.incomplete !== undefined){ -if(typeof data219.incomplete !== "boolean"){ -const err393 = {instancePath:instancePath+"/budgets/" + i16+"/state/incomplete",schemaPath:"#/properties/budgets/items/properties/state/properties/incomplete/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err393]; -} -else { -vErrors.push(err393); -} -errors++; -} -} -} -else { -const err394 = {instancePath:instancePath+"/budgets/" + i16+"/state",schemaPath:"#/properties/budgets/items/properties/state/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err394]; -} -else { -vErrors.push(err394); -} -errors++; -} -} -} -else { -const err395 = {instancePath:instancePath+"/budgets/" + i16,schemaPath:"#/properties/budgets/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err395]; -} -else { -vErrors.push(err395); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data227 = data.accounting; -if(data227 && typeof data227 == "object" && !Array.isArray(data227)){ -if(data227.root_id === undefined){ -const err396 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err396]; -} -else { -vErrors.push(err396); -} -errors++; -} -if(data227.agent_id === undefined){ -const err397 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err397]; -} -else { -vErrors.push(err397); -} -errors++; -} -if(data227.scope === undefined){ -const err398 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err398]; -} -else { -vErrors.push(err398); -} -errors++; -} -if(data227.revision === undefined){ -const err399 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err399]; -} -else { -vErrors.push(err399); -} -errors++; -} -if(data227.reported_cost_micros === undefined){ -const err400 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err400]; -} -else { -vErrors.push(err400); -} -errors++; -} -if(data227.estimated_cost_micros === undefined){ -const err401 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err401]; -} -else { -vErrors.push(err401); -} -errors++; -} -if(data227.reported_cost_calls === undefined){ -const err402 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err402]; -} -else { -vErrors.push(err402); -} -errors++; -} -if(data227.estimated_cost_calls === undefined){ -const err403 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err403]; -} -else { -vErrors.push(err403); -} -errors++; -} -if(data227.unknown_cost_calls === undefined){ -const err404 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err404]; -} -else { -vErrors.push(err404); -} -errors++; -} -if(data227.reported_calls === undefined){ -const err405 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err405]; -} -else { -vErrors.push(err405); -} -errors++; -} -if(data227.estimated_calls === undefined){ -const err406 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err406]; -} -else { -vErrors.push(err406); -} -errors++; -} -if(data227.pending_calls === undefined){ -const err407 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err407]; -} -else { -vErrors.push(err407); -} -errors++; -} -if(data227.root_id !== undefined){ -if(typeof data227.root_id !== "string"){ -const err408 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err408]; -} -else { -vErrors.push(err408); -} -errors++; -} -} -if(data227.agent_id !== undefined){ -if(typeof data227.agent_id !== "string"){ -const err409 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err409]; -} -else { -vErrors.push(err409); -} -errors++; -} -} -if(data227.scope !== undefined){ -if(typeof data227.scope !== "string"){ -const err410 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err410]; -} -else { -vErrors.push(err410); -} -errors++; -} -} -if(data227.revision !== undefined){ -let data231 = data227.revision; -if(typeof data231 === "string"){ -if(!pattern0.test(data231)){ -const err411 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err411]; -} -else { -vErrors.push(err411); -} -errors++; -} -if(!(formats0.validate(data231))){ -const err412 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err412]; -} -else { -vErrors.push(err412); -} -errors++; -} -} -else { -const err413 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err413]; -} -else { -vErrors.push(err413); -} -errors++; -} -} -if(data227.reported_cost_micros !== undefined){ -let data232 = data227.reported_cost_micros; -if(typeof data232 === "string"){ -if(!pattern0.test(data232)){ -const err414 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err414]; -} -else { -vErrors.push(err414); -} -errors++; -} -if(!(formats0.validate(data232))){ -const err415 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err415]; -} -else { -vErrors.push(err415); -} -errors++; -} -} -else { -const err416 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err416]; -} -else { -vErrors.push(err416); -} -errors++; -} -} -if(data227.estimated_cost_micros !== undefined){ -let data233 = data227.estimated_cost_micros; -if(typeof data233 === "string"){ -if(!pattern0.test(data233)){ -const err417 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err417]; -} -else { -vErrors.push(err417); -} -errors++; -} -if(!(formats0.validate(data233))){ -const err418 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err418]; -} -else { -vErrors.push(err418); -} -errors++; -} -} -else { -const err419 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err419]; -} -else { -vErrors.push(err419); -} -errors++; -} -} -if(data227.reported_cost_calls !== undefined){ -let data234 = data227.reported_cost_calls; -if(typeof data234 === "string"){ -if(!pattern0.test(data234)){ -const err420 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err420]; -} -else { -vErrors.push(err420); -} -errors++; -} -if(!(formats0.validate(data234))){ -const err421 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err421]; -} -else { -vErrors.push(err421); -} -errors++; -} -} -else { -const err422 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err422]; -} -else { -vErrors.push(err422); -} -errors++; -} -} -if(data227.estimated_cost_calls !== undefined){ -let data235 = data227.estimated_cost_calls; -if(typeof data235 === "string"){ -if(!pattern0.test(data235)){ -const err423 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err423]; -} -else { -vErrors.push(err423); -} -errors++; -} -if(!(formats0.validate(data235))){ -const err424 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err424]; -} -else { -vErrors.push(err424); -} -errors++; -} -} -else { -const err425 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err425]; -} -else { -vErrors.push(err425); -} -errors++; -} -} -if(data227.unknown_cost_calls !== undefined){ -let data236 = data227.unknown_cost_calls; -if(typeof data236 === "string"){ -if(!pattern0.test(data236)){ -const err426 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err426]; -} -else { -vErrors.push(err426); -} -errors++; -} -if(!(formats0.validate(data236))){ -const err427 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err427]; -} -else { -vErrors.push(err427); -} -errors++; -} -} -else { -const err428 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err428]; -} -else { -vErrors.push(err428); -} -errors++; -} -} -if(data227.reported_calls !== undefined){ -let data237 = data227.reported_calls; -if(typeof data237 === "string"){ -if(!pattern0.test(data237)){ -const err429 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err429]; -} -else { -vErrors.push(err429); -} -errors++; -} -if(!(formats0.validate(data237))){ -const err430 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err430]; -} -else { -vErrors.push(err430); -} -errors++; -} -} -else { -const err431 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err431]; -} -else { -vErrors.push(err431); -} -errors++; -} -} -if(data227.estimated_calls !== undefined){ -let data238 = data227.estimated_calls; -if(typeof data238 === "string"){ -if(!pattern0.test(data238)){ -const err432 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err432]; -} -else { -vErrors.push(err432); -} -errors++; -} -if(!(formats0.validate(data238))){ -const err433 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err433]; -} -else { -vErrors.push(err433); -} -errors++; -} -} -else { -const err434 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err434]; -} -else { -vErrors.push(err434); -} -errors++; -} -} -if(data227.pending_calls !== undefined){ -let data239 = data227.pending_calls; -if(typeof data239 === "string"){ -if(!pattern0.test(data239)){ -const err435 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err435]; -} -else { -vErrors.push(err435); -} -errors++; -} -if(!(formats0.validate(data239))){ -const err436 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err436]; -} -else { -vErrors.push(err436); -} -errors++; -} -} -else { -const err437 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err437]; -} -else { -vErrors.push(err437); -} -errors++; -} -} -} -else { -const err438 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err438]; -} -else { -vErrors.push(err438); -} -errors++; -} -} -if(data.capabilities !== undefined){ -let data240 = data.capabilities; -if((data240 !== null) && (!(Array.isArray(data240)))){ -const err439 = {instancePath:instancePath+"/capabilities",schemaPath:"#/properties/capabilities/type",keyword:"type",params:{type: schema160.properties.capabilities.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err439]; -} -else { -vErrors.push(err439); -} -errors++; -} -if(Array.isArray(data240)){ -const len17 = data240.length; -for(let i17=0; i17<len17; i17++){ -let data241 = data240[i17]; -if(data241 && typeof data241 == "object" && !Array.isArray(data241)){ -if(data241.id === undefined){ -const err440 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err440]; -} -else { -vErrors.push(err440); -} -errors++; -} -if(data241.root_id === undefined){ -const err441 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err441]; -} -else { -vErrors.push(err441); -} -errors++; -} -if(data241.agent_id === undefined){ -const err442 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err442]; -} -else { -vErrors.push(err442); -} -errors++; -} -if(data241.issuer_agent_id === undefined){ -const err443 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "issuer_agent_id"},message:"must have required property '"+"issuer_agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err443]; -} -else { -vErrors.push(err443); -} -errors++; -} -if(data241.operations === undefined){ -const err444 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "operations"},message:"must have required property '"+"operations"+"'"}; -if(vErrors === null){ -vErrors = [err444]; -} -else { -vErrors.push(err444); -} -errors++; -} -if(data241.scopes === undefined){ -const err445 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "scopes"},message:"must have required property '"+"scopes"+"'"}; -if(vErrors === null){ -vErrors = [err445]; -} -else { -vErrors.push(err445); -} -errors++; -} -if(data241.mcp === undefined){ -const err446 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "mcp"},message:"must have required property '"+"mcp"+"'"}; -if(vErrors === null){ -vErrors = [err446]; -} -else { -vErrors.push(err446); -} -errors++; -} -if(data241.mcp_all === undefined){ -const err447 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "mcp_all"},message:"must have required property '"+"mcp_all"+"'"}; -if(vErrors === null){ -vErrors = [err447]; -} -else { -vErrors.push(err447); -} -errors++; -} -if(data241.generation === undefined){ -const err448 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err448]; -} -else { -vErrors.push(err448); -} -errors++; -} -if(data241.status === undefined){ -const err449 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err449]; -} -else { -vErrors.push(err449); -} -errors++; -} -if(data241.expires_at === undefined){ -const err450 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "expires_at"},message:"must have required property '"+"expires_at"+"'"}; -if(vErrors === null){ -vErrors = [err450]; -} -else { -vErrors.push(err450); -} -errors++; -} -if(data241.created_at === undefined){ -const err451 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "created_at"},message:"must have required property '"+"created_at"+"'"}; -if(vErrors === null){ -vErrors = [err451]; -} -else { -vErrors.push(err451); -} -errors++; -} -if(data241.updated_at === undefined){ -const err452 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err452]; -} -else { -vErrors.push(err452); -} -errors++; -} -if(data241.id !== undefined){ -if(typeof data241.id !== "string"){ -const err453 = {instancePath:instancePath+"/capabilities/" + i17+"/id",schemaPath:"#/properties/capabilities/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err453]; -} -else { -vErrors.push(err453); -} -errors++; -} -} -if(data241.root_id !== undefined){ -if(typeof data241.root_id !== "string"){ -const err454 = {instancePath:instancePath+"/capabilities/" + i17+"/root_id",schemaPath:"#/properties/capabilities/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err454]; -} -else { -vErrors.push(err454); -} -errors++; -} -} -if(data241.agent_id !== undefined){ -if(typeof data241.agent_id !== "string"){ -const err455 = {instancePath:instancePath+"/capabilities/" + i17+"/agent_id",schemaPath:"#/properties/capabilities/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err455]; -} -else { -vErrors.push(err455); -} -errors++; -} -} -if(data241.issuer_agent_id !== undefined){ -if(typeof data241.issuer_agent_id !== "string"){ -const err456 = {instancePath:instancePath+"/capabilities/" + i17+"/issuer_agent_id",schemaPath:"#/properties/capabilities/items/properties/issuer_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err456]; -} -else { -vErrors.push(err456); -} -errors++; -} -} -if(data241.operations !== undefined){ -let data246 = data241.operations; -if((data246 !== null) && (!(Array.isArray(data246)))){ -const err457 = {instancePath:instancePath+"/capabilities/" + i17+"/operations",schemaPath:"#/properties/capabilities/items/properties/operations/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.operations.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err457]; -} -else { -vErrors.push(err457); -} -errors++; -} -if(Array.isArray(data246)){ -const len18 = data246.length; -for(let i18=0; i18<len18; i18++){ -if(typeof data246[i18] !== "string"){ -const err458 = {instancePath:instancePath+"/capabilities/" + i17+"/operations/" + i18,schemaPath:"#/properties/capabilities/items/properties/operations/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err458]; -} -else { -vErrors.push(err458); -} -errors++; -} -} -} -} -if(data241.scopes !== undefined){ -let data248 = data241.scopes; -if((data248 !== null) && (!(Array.isArray(data248)))){ -const err459 = {instancePath:instancePath+"/capabilities/" + i17+"/scopes",schemaPath:"#/properties/capabilities/items/properties/scopes/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.scopes.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err459]; -} -else { -vErrors.push(err459); -} -errors++; -} -if(Array.isArray(data248)){ -const len19 = data248.length; -for(let i19=0; i19<len19; i19++){ -if(typeof data248[i19] !== "string"){ -const err460 = {instancePath:instancePath+"/capabilities/" + i17+"/scopes/" + i19,schemaPath:"#/properties/capabilities/items/properties/scopes/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err460]; -} -else { -vErrors.push(err460); -} -errors++; -} -} -} -} -if(data241.file_scope !== undefined){ -if(typeof data241.file_scope !== "string"){ -const err461 = {instancePath:instancePath+"/capabilities/" + i17+"/file_scope",schemaPath:"#/properties/capabilities/items/properties/file_scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err461]; -} -else { -vErrors.push(err461); -} -errors++; -} -} -if(data241.file_issuer_id !== undefined){ -if(typeof data241.file_issuer_id !== "string"){ -const err462 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_id",schemaPath:"#/properties/capabilities/items/properties/file_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err462]; -} -else { -vErrors.push(err462); -} -errors++; -} -} -if(data241.file_issuer_generation !== undefined){ -let data252 = data241.file_issuer_generation; -if(typeof data252 === "string"){ -if(!pattern0.test(data252)){ -const err463 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err463]; -} -else { -vErrors.push(err463); -} -errors++; -} -if(!(formats0.validate(data252))){ -const err464 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err464]; -} -else { -vErrors.push(err464); -} -errors++; -} -} -else { -const err465 = {instancePath:instancePath+"/capabilities/" + i17+"/file_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/file_issuer_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err465]; -} -else { -vErrors.push(err465); -} -errors++; -} -} -if(data241.mcp !== undefined){ -let data253 = data241.mcp; -if((data253 !== null) && (!(Array.isArray(data253)))){ -const err466 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp",schemaPath:"#/properties/capabilities/items/properties/mcp/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.mcp.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err466]; -} -else { -vErrors.push(err466); -} -errors++; -} -if(Array.isArray(data253)){ -const len20 = data253.length; -for(let i20=0; i20<len20; i20++){ -let data254 = data253[i20]; -if(data254 && typeof data254 == "object" && !Array.isArray(data254)){ -if(data254.server === undefined){ -const err467 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "server"},message:"must have required property '"+"server"+"'"}; -if(vErrors === null){ -vErrors = [err467]; -} -else { -vErrors.push(err467); -} -errors++; -} -if(data254.tool === undefined){ -const err468 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err468]; -} -else { -vErrors.push(err468); -} -errors++; -} -if(data254.definition === undefined){ -const err469 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err469]; -} -else { -vErrors.push(err469); -} -errors++; -} -if(data254.server !== undefined){ -if(typeof data254.server !== "string"){ -const err470 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/server",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/server/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err470]; -} -else { -vErrors.push(err470); -} -errors++; -} -} -if(data254.tool !== undefined){ -if(typeof data254.tool !== "string"){ -const err471 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/tool",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err471]; -} -else { -vErrors.push(err471); -} -errors++; -} -} -if(data254.definition !== undefined){ -if(typeof data254.definition !== "string"){ -const err472 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20+"/definition",schemaPath:"#/properties/capabilities/items/properties/mcp/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err472]; -} -else { -vErrors.push(err472); -} -errors++; -} -} -} -else { -const err473 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp/" + i20,schemaPath:"#/properties/capabilities/items/properties/mcp/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err473]; -} -else { -vErrors.push(err473); -} -errors++; -} -} -} -} -if(data241.mcp_all !== undefined){ -if(typeof data241.mcp_all !== "boolean"){ -const err474 = {instancePath:instancePath+"/capabilities/" + i17+"/mcp_all",schemaPath:"#/properties/capabilities/items/properties/mcp_all/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err474]; -} -else { -vErrors.push(err474); -} -errors++; -} -} -if(data241.browser !== undefined){ -let data259 = data241.browser; -if((data259 !== null) && (!(data259 && typeof data259 == "object" && !Array.isArray(data259)))){ -const err475 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err475]; -} -else { -vErrors.push(err475); -} -errors++; -} -if(data259 && typeof data259 == "object" && !Array.isArray(data259)){ -if(data259.provider_id === undefined){ -const err476 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "provider_id"},message:"must have required property '"+"provider_id"+"'"}; -if(vErrors === null){ -vErrors = [err476]; -} -else { -vErrors.push(err476); -} -errors++; -} -if(data259.provider_epoch === undefined){ -const err477 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "provider_epoch"},message:"must have required property '"+"provider_epoch"+"'"}; -if(vErrors === null){ -vErrors = [err477]; -} -else { -vErrors.push(err477); -} -errors++; -} -if(data259.tab_id === undefined){ -const err478 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "tab_id"},message:"must have required property '"+"tab_id"+"'"}; -if(vErrors === null){ -vErrors = [err478]; -} -else { -vErrors.push(err478); -} -errors++; -} -if(data259.tab_generation === undefined){ -const err479 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "tab_generation"},message:"must have required property '"+"tab_generation"+"'"}; -if(vErrors === null){ -vErrors = [err479]; -} -else { -vErrors.push(err479); -} -errors++; -} -if(data259.profile_id === undefined){ -const err480 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "profile_id"},message:"must have required property '"+"profile_id"+"'"}; -if(vErrors === null){ -vErrors = [err480]; -} -else { -vErrors.push(err480); -} -errors++; -} -if(data259.rights === undefined){ -const err481 = {instancePath:instancePath+"/capabilities/" + i17+"/browser",schemaPath:"#/properties/capabilities/items/properties/browser/required",keyword:"required",params:{missingProperty: "rights"},message:"must have required property '"+"rights"+"'"}; -if(vErrors === null){ -vErrors = [err481]; -} -else { -vErrors.push(err481); -} -errors++; -} -if(data259.provider_id !== undefined){ -if(typeof data259.provider_id !== "string"){ -const err482 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/provider_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/provider_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err482]; -} -else { -vErrors.push(err482); -} -errors++; -} -} -if(data259.provider_epoch !== undefined){ -if(typeof data259.provider_epoch !== "string"){ -const err483 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/provider_epoch",schemaPath:"#/properties/capabilities/items/properties/browser/properties/provider_epoch/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err483]; -} -else { -vErrors.push(err483); -} -errors++; -} -} -if(data259.tab_id !== undefined){ -if(typeof data259.tab_id !== "string"){ -const err484 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/tab_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/tab_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err484]; -} -else { -vErrors.push(err484); -} -errors++; -} -} -if(data259.tab_generation !== undefined){ -if(typeof data259.tab_generation !== "string"){ -const err485 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/tab_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/tab_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err485]; -} -else { -vErrors.push(err485); -} -errors++; -} -} -if(data259.profile_id !== undefined){ -if(typeof data259.profile_id !== "string"){ -const err486 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/profile_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/profile_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err486]; -} -else { -vErrors.push(err486); -} -errors++; -} -} -if(data259.attachment_id !== undefined){ -if(typeof data259.attachment_id !== "string"){ -const err487 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/attachment_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err487]; -} -else { -vErrors.push(err487); -} -errors++; -} -} -if(data259.attachment_generation !== undefined){ -if(typeof data259.attachment_generation !== "string"){ -const err488 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/attachment_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/attachment_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err488]; -} -else { -vErrors.push(err488); -} -errors++; -} -} -if(data259.rights !== undefined){ -let data267 = data259.rights; -if((data267 !== null) && (!(Array.isArray(data267)))){ -const err489 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/rights",schemaPath:"#/properties/capabilities/items/properties/browser/properties/rights/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.rights.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err489]; -} -else { -vErrors.push(err489); -} -errors++; -} -if(Array.isArray(data267)){ -const len21 = data267.length; -for(let i21=0; i21<len21; i21++){ -if(typeof data267[i21] !== "string"){ -const err490 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/rights/" + i21,schemaPath:"#/properties/capabilities/items/properties/browser/properties/rights/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err490]; -} -else { -vErrors.push(err490); -} -errors++; -} -} -} -} -if(data259.preview !== undefined){ -let data269 = data259.preview; -if((data269 !== null) && (!(data269 && typeof data269 == "object" && !Array.isArray(data269)))){ -const err491 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.preview.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err491]; -} -else { -vErrors.push(err491); -} -errors++; -} -if(data269 && typeof data269 == "object" && !Array.isArray(data269)){ -if(data269.host_id === undefined){ -const err492 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_id"},message:"must have required property '"+"host_id"+"'"}; -if(vErrors === null){ -vErrors = [err492]; -} -else { -vErrors.push(err492); -} -errors++; -} -if(data269.host_identity === undefined){ -const err493 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "host_identity"},message:"must have required property '"+"host_identity"+"'"}; -if(vErrors === null){ -vErrors = [err493]; -} -else { -vErrors.push(err493); -} -errors++; -} -if(data269.connection_generation === undefined){ -const err494 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "connection_generation"},message:"must have required property '"+"connection_generation"+"'"}; -if(vErrors === null){ -vErrors = [err494]; -} -else { -vErrors.push(err494); -} -errors++; -} -if(data269.environment_id === undefined){ -const err495 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "environment_id"},message:"must have required property '"+"environment_id"+"'"}; -if(vErrors === null){ -vErrors = [err495]; -} -else { -vErrors.push(err495); -} -errors++; -} -if(data269.loopback === undefined){ -const err496 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "loopback"},message:"must have required property '"+"loopback"+"'"}; -if(vErrors === null){ -vErrors = [err496]; -} -else { -vErrors.push(err496); -} -errors++; -} -if(data269.ports === undefined){ -const err497 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/required",keyword:"required",params:{missingProperty: "ports"},message:"must have required property '"+"ports"+"'"}; -if(vErrors === null){ -vErrors = [err497]; -} -else { -vErrors.push(err497); -} -errors++; -} -if(data269.host_id !== undefined){ -if(typeof data269.host_id !== "string"){ -const err498 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/host_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/host_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err498]; -} -else { -vErrors.push(err498); -} -errors++; -} -} -if(data269.host_identity !== undefined){ -if(typeof data269.host_identity !== "string"){ -const err499 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/host_identity",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/host_identity/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err499]; -} -else { -vErrors.push(err499); -} -errors++; -} -} -if(data269.connection_generation !== undefined){ -if(typeof data269.connection_generation !== "string"){ -const err500 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/connection_generation",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/connection_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err500]; -} -else { -vErrors.push(err500); -} -errors++; -} -} -if(data269.environment_id !== undefined){ -if(typeof data269.environment_id !== "string"){ -const err501 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/environment_id",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/environment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err501]; -} -else { -vErrors.push(err501); -} -errors++; -} -} -if(data269.loopback !== undefined){ -if(typeof data269.loopback !== "string"){ -const err502 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/loopback",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/loopback/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err502]; -} -else { -vErrors.push(err502); -} -errors++; -} -} -if(data269.ports !== undefined){ -let data275 = data269.ports; -if((data275 !== null) && (!(Array.isArray(data275)))){ -const err503 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/ports",schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/ports/type",keyword:"type",params:{type: schema160.properties.capabilities.items.properties.browser.properties.preview.properties.ports.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err503]; -} -else { -vErrors.push(err503); -} -errors++; -} -if(Array.isArray(data275)){ -const len22 = data275.length; -for(let i22=0; i22<len22; i22++){ -let data276 = data275[i22]; -if(!((typeof data276 == "number") && (!(data276 % 1) && !isNaN(data276)))){ -const err504 = {instancePath:instancePath+"/capabilities/" + i17+"/browser/preview/ports/" + i22,schemaPath:"#/properties/capabilities/items/properties/browser/properties/preview/properties/ports/items/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err504]; -} -else { -vErrors.push(err504); -} -errors++; -} -} -} -} -} -} -} -} -if(data241.browser_issuer_id !== undefined){ -if(typeof data241.browser_issuer_id !== "string"){ -const err505 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_issuer_id",schemaPath:"#/properties/capabilities/items/properties/browser_issuer_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err505]; -} -else { -vErrors.push(err505); -} -errors++; -} -} -if(data241.browser_issuer_generation !== undefined){ -let data278 = data241.browser_issuer_generation; -if(!((typeof data278 == "number") && (!(data278 % 1) && !isNaN(data278)))){ -const err506 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_issuer_generation",schemaPath:"#/properties/capabilities/items/properties/browser_issuer_generation/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err506]; -} -else { -vErrors.push(err506); -} -errors++; -} -} -if(data241.browser_delegation_only !== undefined){ -if(typeof data241.browser_delegation_only !== "boolean"){ -const err507 = {instancePath:instancePath+"/capabilities/" + i17+"/browser_delegation_only",schemaPath:"#/properties/capabilities/items/properties/browser_delegation_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err507]; -} -else { -vErrors.push(err507); -} -errors++; -} -} -if(data241.generation !== undefined){ -let data280 = data241.generation; -if(typeof data280 === "string"){ -if(!pattern0.test(data280)){ -const err508 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err508]; -} -else { -vErrors.push(err508); -} -errors++; -} -if(!(formats0.validate(data280))){ -const err509 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err509]; -} -else { -vErrors.push(err509); -} -errors++; -} -} -else { -const err510 = {instancePath:instancePath+"/capabilities/" + i17+"/generation",schemaPath:"#/properties/capabilities/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err510]; -} -else { -vErrors.push(err510); -} -errors++; -} -} -if(data241.status !== undefined){ -if(typeof data241.status !== "string"){ -const err511 = {instancePath:instancePath+"/capabilities/" + i17+"/status",schemaPath:"#/properties/capabilities/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err511]; -} -else { -vErrors.push(err511); -} -errors++; -} -} -if(data241.expires_at !== undefined){ -if(typeof data241.expires_at !== "string"){ -const err512 = {instancePath:instancePath+"/capabilities/" + i17+"/expires_at",schemaPath:"#/properties/capabilities/items/properties/expires_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err512]; -} -else { -vErrors.push(err512); -} -errors++; -} -} -if(data241.created_at !== undefined){ -if(typeof data241.created_at !== "string"){ -const err513 = {instancePath:instancePath+"/capabilities/" + i17+"/created_at",schemaPath:"#/properties/capabilities/items/properties/created_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err513]; -} -else { -vErrors.push(err513); -} -errors++; -} -} -if(data241.updated_at !== undefined){ -if(typeof data241.updated_at !== "string"){ -const err514 = {instancePath:instancePath+"/capabilities/" + i17+"/updated_at",schemaPath:"#/properties/capabilities/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err514]; -} -else { -vErrors.push(err514); -} -errors++; -} -} -} -else { -const err515 = {instancePath:instancePath+"/capabilities/" + i17,schemaPath:"#/properties/capabilities/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err515]; -} -else { -vErrors.push(err515); -} -errors++; -} -} -} -} -if(data.schedules !== undefined){ -let data285 = data.schedules; -if((data285 !== null) && (!(Array.isArray(data285)))){ -const err516 = {instancePath:instancePath+"/schedules",schemaPath:"#/properties/schedules/type",keyword:"type",params:{type: schema160.properties.schedules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err516]; -} -else { -vErrors.push(err516); -} -errors++; -} -if(Array.isArray(data285)){ -const len23 = data285.length; -for(let i23=0; i23<len23; i23++){ -let data286 = data285[i23]; -if(data286 && typeof data286 == "object" && !Array.isArray(data286)){ -if(data286.id === undefined){ -const err517 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err517]; -} -else { -vErrors.push(err517); -} -errors++; -} -if(data286.schedule === undefined){ -const err518 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err518]; -} -else { -vErrors.push(err518); -} -errors++; -} -if(data286.prompt === undefined){ -const err519 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err519]; -} -else { -vErrors.push(err519); -} -errors++; -} -if(data286.anchor === undefined){ -const err520 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err520]; -} -else { -vErrors.push(err520); -} -errors++; -} -if(data286.last_fire === undefined){ -const err521 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err521]; -} -else { -vErrors.push(err521); -} -errors++; -} -if(data286.id !== undefined){ -let data287 = data286.id; -if(!((typeof data287 == "number") && (!(data287 % 1) && !isNaN(data287)))){ -const err522 = {instancePath:instancePath+"/schedules/" + i23+"/id",schemaPath:"#/properties/schedules/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err522]; -} -else { -vErrors.push(err522); -} -errors++; -} -} -if(data286.schedule !== undefined){ -if(typeof data286.schedule !== "string"){ -const err523 = {instancePath:instancePath+"/schedules/" + i23+"/schedule",schemaPath:"#/properties/schedules/items/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err523]; -} -else { -vErrors.push(err523); -} -errors++; -} -} -if(data286.prompt !== undefined){ -if(typeof data286.prompt !== "string"){ -const err524 = {instancePath:instancePath+"/schedules/" + i23+"/prompt",schemaPath:"#/properties/schedules/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err524]; -} -else { -vErrors.push(err524); -} -errors++; -} -} -if(data286.anchor !== undefined){ -if(typeof data286.anchor !== "string"){ -const err525 = {instancePath:instancePath+"/schedules/" + i23+"/anchor",schemaPath:"#/properties/schedules/items/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err525]; -} -else { -vErrors.push(err525); -} -errors++; -} -} -if(data286.last_fire !== undefined){ -if(typeof data286.last_fire !== "string"){ -const err526 = {instancePath:instancePath+"/schedules/" + i23+"/last_fire",schemaPath:"#/properties/schedules/items/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err526]; -} -else { -vErrors.push(err526); -} -errors++; -} -} -} -else { -const err527 = {instancePath:instancePath+"/schedules/" + i23,schemaPath:"#/properties/schedules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err527]; -} -else { -vErrors.push(err527); -} -errors++; -} -} -} -} -if(data.upcoming_schedules !== undefined){ -let data292 = data.upcoming_schedules; -if((data292 !== null) && (!(Array.isArray(data292)))){ -const err528 = {instancePath:instancePath+"/upcoming_schedules",schemaPath:"#/properties/upcoming_schedules/type",keyword:"type",params:{type: schema160.properties.upcoming_schedules.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err528]; -} -else { -vErrors.push(err528); -} -errors++; -} -if(Array.isArray(data292)){ -const len24 = data292.length; -for(let i24=0; i24<len24; i24++){ -let data293 = data292[i24]; -if(data293 && typeof data293 == "object" && !Array.isArray(data293)){ -if(data293.id === undefined){ -const err529 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err529]; -} -else { -vErrors.push(err529); -} -errors++; -} -if(data293.next_fire === undefined){ -const err530 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "next_fire"},message:"must have required property '"+"next_fire"+"'"}; -if(vErrors === null){ -vErrors = [err530]; -} -else { -vErrors.push(err530); -} -errors++; -} -if(data293.prompt === undefined){ -const err531 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err531]; -} -else { -vErrors.push(err531); -} -errors++; -} -if(data293.id !== undefined){ -let data294 = data293.id; -if(!((typeof data294 == "number") && (!(data294 % 1) && !isNaN(data294)))){ -const err532 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/id",schemaPath:"#/properties/upcoming_schedules/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err532]; -} -else { -vErrors.push(err532); -} -errors++; -} -} -if(data293.next_fire !== undefined){ -if(typeof data293.next_fire !== "string"){ -const err533 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/next_fire",schemaPath:"#/properties/upcoming_schedules/items/properties/next_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err533]; -} -else { -vErrors.push(err533); -} -errors++; -} -} -if(data293.prompt !== undefined){ -if(typeof data293.prompt !== "string"){ -const err534 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/prompt",schemaPath:"#/properties/upcoming_schedules/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err534]; -} -else { -vErrors.push(err534); -} -errors++; -} -} -if(data293.prompt_truncated !== undefined){ -if(typeof data293.prompt_truncated !== "boolean"){ -const err535 = {instancePath:instancePath+"/upcoming_schedules/" + i24+"/prompt_truncated",schemaPath:"#/properties/upcoming_schedules/items/properties/prompt_truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err535]; -} -else { -vErrors.push(err535); -} -errors++; -} -} -} -else { -const err536 = {instancePath:instancePath+"/upcoming_schedules/" + i24,schemaPath:"#/properties/upcoming_schedules/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err536]; -} -else { -vErrors.push(err536); -} -errors++; -} -} -} -} -if(data.upcoming_schedule_count !== undefined){ -let data298 = data.upcoming_schedule_count; -if((data298 !== null) && (!((typeof data298 == "number") && (!(data298 % 1) && !isNaN(data298))))){ -const err537 = {instancePath:instancePath+"/upcoming_schedule_count",schemaPath:"#/properties/upcoming_schedule_count/type",keyword:"type",params:{type: schema160.properties.upcoming_schedule_count.type},message:"must be null,integer"}; -if(vErrors === null){ -vErrors = [err537]; -} -else { -vErrors.push(err537); -} -errors++; -} -} -if(data.permissions !== undefined){ -let data299 = data.permissions; -if((data299 !== null) && (!(Array.isArray(data299)))){ -const err538 = {instancePath:instancePath+"/permissions",schemaPath:"#/properties/permissions/type",keyword:"type",params:{type: schema160.properties.permissions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err538]; -} -else { -vErrors.push(err538); -} -errors++; -} -if(Array.isArray(data299)){ -const len25 = data299.length; -for(let i25=0; i25<len25; i25++){ -let data300 = data299[i25]; -if(data300 && typeof data300 == "object" && !Array.isArray(data300)){ -if(data300.id === undefined){ -const err539 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err539]; -} -else { -vErrors.push(err539); -} -errors++; -} -if(data300.agent_id === undefined){ -const err540 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err540]; -} -else { -vErrors.push(err540); -} -errors++; -} -if(data300.operation_id === undefined){ -const err541 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "operation_id"},message:"must have required property '"+"operation_id"+"'"}; -if(vErrors === null){ -vErrors = [err541]; -} -else { -vErrors.push(err541); -} -errors++; -} -if(data300.operation === undefined){ -const err542 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "operation"},message:"must have required property '"+"operation"+"'"}; -if(vErrors === null){ -vErrors = [err542]; -} -else { -vErrors.push(err542); -} -errors++; -} -if(data300.canonical_path === undefined){ -const err543 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "canonical_path"},message:"must have required property '"+"canonical_path"+"'"}; -if(vErrors === null){ -vErrors = [err543]; -} -else { -vErrors.push(err543); -} -errors++; -} -if(data300.request_digest === undefined){ -const err544 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "request_digest"},message:"must have required property '"+"request_digest"+"'"}; -if(vErrors === null){ -vErrors = [err544]; -} -else { -vErrors.push(err544); -} -errors++; -} -if(data300.capability_id === undefined){ -const err545 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "capability_id"},message:"must have required property '"+"capability_id"+"'"}; -if(vErrors === null){ -vErrors = [err545]; -} -else { -vErrors.push(err545); -} -errors++; -} -if(data300.capability_generation === undefined){ -const err546 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "capability_generation"},message:"must have required property '"+"capability_generation"+"'"}; -if(vErrors === null){ -vErrors = [err546]; -} -else { -vErrors.push(err546); -} -errors++; -} -if(data300.status === undefined){ -const err547 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err547]; -} -else { -vErrors.push(err547); -} -errors++; -} -if(data300.command === undefined){ -const err548 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err548]; -} -else { -vErrors.push(err548); -} -errors++; -} -if(data300.rule === undefined){ -const err549 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/required",keyword:"required",params:{missingProperty: "rule"},message:"must have required property '"+"rule"+"'"}; -if(vErrors === null){ -vErrors = [err549]; -} -else { -vErrors.push(err549); -} -errors++; -} -if(data300.id !== undefined){ -if(typeof data300.id !== "string"){ -const err550 = {instancePath:instancePath+"/permissions/" + i25+"/id",schemaPath:"#/properties/permissions/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err550]; -} -else { -vErrors.push(err550); -} -errors++; -} -} -if(data300.agent_id !== undefined){ -if(typeof data300.agent_id !== "string"){ -const err551 = {instancePath:instancePath+"/permissions/" + i25+"/agent_id",schemaPath:"#/properties/permissions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err551]; -} -else { -vErrors.push(err551); -} -errors++; -} -} -if(data300.operation_id !== undefined){ -if(typeof data300.operation_id !== "string"){ -const err552 = {instancePath:instancePath+"/permissions/" + i25+"/operation_id",schemaPath:"#/properties/permissions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err552]; -} -else { -vErrors.push(err552); -} -errors++; -} -} -if(data300.operation !== undefined){ -if(typeof data300.operation !== "string"){ -const err553 = {instancePath:instancePath+"/permissions/" + i25+"/operation",schemaPath:"#/properties/permissions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err553]; -} -else { -vErrors.push(err553); -} -errors++; -} -} -if(data300.canonical_path !== undefined){ -if(typeof data300.canonical_path !== "string"){ -const err554 = {instancePath:instancePath+"/permissions/" + i25+"/canonical_path",schemaPath:"#/properties/permissions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err554]; -} -else { -vErrors.push(err554); -} -errors++; -} -} -if(data300.request_digest !== undefined){ -if(typeof data300.request_digest !== "string"){ -const err555 = {instancePath:instancePath+"/permissions/" + i25+"/request_digest",schemaPath:"#/properties/permissions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err555]; -} -else { -vErrors.push(err555); -} -errors++; -} -} -if(data300.capability_id !== undefined){ -if(typeof data300.capability_id !== "string"){ -const err556 = {instancePath:instancePath+"/permissions/" + i25+"/capability_id",schemaPath:"#/properties/permissions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err556]; -} -else { -vErrors.push(err556); -} -errors++; -} -} -if(data300.capability_generation !== undefined){ -let data308 = data300.capability_generation; -if(typeof data308 === "string"){ -if(!pattern0.test(data308)){ -const err557 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err557]; -} -else { -vErrors.push(err557); -} -errors++; -} -if(!(formats0.validate(data308))){ -const err558 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err558]; -} -else { -vErrors.push(err558); -} -errors++; -} -} -else { -const err559 = {instancePath:instancePath+"/permissions/" + i25+"/capability_generation",schemaPath:"#/properties/permissions/items/properties/capability_generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err559]; -} -else { -vErrors.push(err559); -} -errors++; -} -} -if(data300.status !== undefined){ -if(typeof data300.status !== "string"){ -const err560 = {instancePath:instancePath+"/permissions/" + i25+"/status",schemaPath:"#/properties/permissions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err560]; -} -else { -vErrors.push(err560); -} -errors++; -} -} -if(data300.command !== undefined){ -if(typeof data300.command !== "string"){ -const err561 = {instancePath:instancePath+"/permissions/" + i25+"/command",schemaPath:"#/properties/permissions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err561]; -} -else { -vErrors.push(err561); -} -errors++; -} -} -if(data300.rule !== undefined){ -if(typeof data300.rule !== "string"){ -const err562 = {instancePath:instancePath+"/permissions/" + i25+"/rule",schemaPath:"#/properties/permissions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err562]; -} -else { -vErrors.push(err562); -} -errors++; -} -} -} -else { -const err563 = {instancePath:instancePath+"/permissions/" + i25,schemaPath:"#/properties/permissions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err563]; -} -else { -vErrors.push(err563); -} -errors++; -} -} -} -} -if(data.questions !== undefined){ -let data312 = data.questions; -if((data312 !== null) && (!(Array.isArray(data312)))){ -const err564 = {instancePath:instancePath+"/questions",schemaPath:"#/properties/questions/type",keyword:"type",params:{type: schema160.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err564]; -} -else { -vErrors.push(err564); -} -errors++; -} -if(Array.isArray(data312)){ -const len26 = data312.length; -for(let i26=0; i26<len26; i26++){ -let data313 = data312[i26]; -if(data313 && typeof data313 == "object" && !Array.isArray(data313)){ -if(data313.turn_id !== undefined){ -if(typeof data313.turn_id !== "string"){ -const err565 = {instancePath:instancePath+"/questions/" + i26+"/turn_id",schemaPath:"#/properties/questions/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err565]; -} -else { -vErrors.push(err565); -} -errors++; -} -} -if(data313.root_id !== undefined){ -if(typeof data313.root_id !== "string"){ -const err566 = {instancePath:instancePath+"/questions/" + i26+"/root_id",schemaPath:"#/properties/questions/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err566]; -} -else { -vErrors.push(err566); -} -errors++; -} -} -if(data313.agent_id !== undefined){ -if(typeof data313.agent_id !== "string"){ -const err567 = {instancePath:instancePath+"/questions/" + i26+"/agent_id",schemaPath:"#/properties/questions/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err567]; -} -else { -vErrors.push(err567); -} -errors++; -} -} -if(data313.sender_agent_id !== undefined){ -if(typeof data313.sender_agent_id !== "string"){ -const err568 = {instancePath:instancePath+"/questions/" + i26+"/sender_agent_id",schemaPath:"#/properties/questions/items/properties/sender_agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err568]; -} -else { -vErrors.push(err568); -} -errors++; -} -} -if(data313.inbox_seq !== undefined){ -let data318 = data313.inbox_seq; -if(typeof data318 === "string"){ -if(!pattern0.test(data318)){ -const err569 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err569]; -} -else { -vErrors.push(err569); -} -errors++; -} -if(!(formats0.validate(data318))){ -const err570 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err570]; -} -else { -vErrors.push(err570); -} -errors++; -} -} -else { -const err571 = {instancePath:instancePath+"/questions/" + i26+"/inbox_seq",schemaPath:"#/properties/questions/items/properties/inbox_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err571]; -} -else { -vErrors.push(err571); -} -errors++; -} -} -if(data313.inbox_kind !== undefined){ -if(typeof data313.inbox_kind !== "string"){ -const err572 = {instancePath:instancePath+"/questions/" + i26+"/inbox_kind",schemaPath:"#/properties/questions/items/properties/inbox_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err572]; -} -else { -vErrors.push(err572); -} -errors++; -} -} -if(data313.delivery !== undefined){ -if(typeof data313.delivery !== "string"){ -const err573 = {instancePath:instancePath+"/questions/" + i26+"/delivery",schemaPath:"#/properties/questions/items/properties/delivery/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err573]; -} -else { -vErrors.push(err573); -} -errors++; -} -} -if(data313.message_id !== undefined){ -if(typeof data313.message_id !== "string"){ -const err574 = {instancePath:instancePath+"/questions/" + i26+"/message_id",schemaPath:"#/properties/questions/items/properties/message_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err574]; -} -else { -vErrors.push(err574); -} -errors++; -} -} -if(data313.phase !== undefined){ -if(typeof data313.phase !== "string"){ -const err575 = {instancePath:instancePath+"/questions/" + i26+"/phase",schemaPath:"#/properties/questions/items/properties/phase/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err575]; -} -else { -vErrors.push(err575); -} -errors++; -} -} -if(data313.status !== undefined){ -if(typeof data313.status !== "string"){ -const err576 = {instancePath:instancePath+"/questions/" + i26+"/status",schemaPath:"#/properties/questions/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err576]; -} -else { -vErrors.push(err576); -} -errors++; -} -} -if(data313.terminal_cause !== undefined){ -if(typeof data313.terminal_cause !== "string"){ -const err577 = {instancePath:instancePath+"/questions/" + i26+"/terminal_cause",schemaPath:"#/properties/questions/items/properties/terminal_cause/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err577]; -} -else { -vErrors.push(err577); -} -errors++; -} -} -if(data313.command_client_id !== undefined){ -if(typeof data313.command_client_id !== "string"){ -const err578 = {instancePath:instancePath+"/questions/" + i26+"/command_client_id",schemaPath:"#/properties/questions/items/properties/command_client_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err578]; -} -else { -vErrors.push(err578); -} -errors++; -} -} -if(data313.command_id !== undefined){ -if(typeof data313.command_id !== "string"){ -const err579 = {instancePath:instancePath+"/questions/" + i26+"/command_id",schemaPath:"#/properties/questions/items/properties/command_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err579]; -} -else { -vErrors.push(err579); -} -errors++; -} -} -if(data313.operation_id !== undefined){ -if(typeof data313.operation_id !== "string"){ -const err580 = {instancePath:instancePath+"/questions/" + i26+"/operation_id",schemaPath:"#/properties/questions/items/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err580]; -} -else { -vErrors.push(err580); -} -errors++; -} -} -if(data313.trace_id !== undefined){ -if(typeof data313.trace_id !== "string"){ -const err581 = {instancePath:instancePath+"/questions/" + i26+"/trace_id",schemaPath:"#/properties/questions/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err581]; -} -else { -vErrors.push(err581); -} -errors++; -} -} -if(data313.schedule_id !== undefined){ -let data329 = data313.schedule_id; -if(!((typeof data329 == "number") && (!(data329 % 1) && !isNaN(data329)))){ -const err582 = {instancePath:instancePath+"/questions/" + i26+"/schedule_id",schemaPath:"#/properties/questions/items/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err582]; -} -else { -vErrors.push(err582); -} -errors++; -} -} -if(data313.slot !== undefined){ -if(typeof data313.slot !== "string"){ -const err583 = {instancePath:instancePath+"/questions/" + i26+"/slot",schemaPath:"#/properties/questions/items/properties/slot/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err583]; -} -else { -vErrors.push(err583); -} -errors++; -} -} -if(data313.error !== undefined){ -if(typeof data313.error !== "string"){ -const err584 = {instancePath:instancePath+"/questions/" + i26+"/error",schemaPath:"#/properties/questions/items/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err584]; -} -else { -vErrors.push(err584); -} -errors++; -} -} -if(data313.model_call !== undefined){ -let data332 = data313.model_call; -if((data332 !== null) && (!(data332 && typeof data332 == "object" && !Array.isArray(data332)))){ -const err585 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.model_call.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err585]; -} -else { -vErrors.push(err585); -} -errors++; -} -if(data332 && typeof data332 == "object" && !Array.isArray(data332)){ -if(data332.id === undefined){ -const err586 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err586]; -} -else { -vErrors.push(err586); -} -errors++; -} -if(data332.logical_id === undefined){ -const err587 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "logical_id"},message:"must have required property '"+"logical_id"+"'"}; -if(vErrors === null){ -vErrors = [err587]; -} -else { -vErrors.push(err587); -} -errors++; -} -if(data332.number === undefined){ -const err588 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "number"},message:"must have required property '"+"number"+"'"}; -if(vErrors === null){ -vErrors = [err588]; -} -else { -vErrors.push(err588); -} -errors++; -} -if(data332.purpose === undefined){ -const err589 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "purpose"},message:"must have required property '"+"purpose"+"'"}; -if(vErrors === null){ -vErrors = [err589]; -} -else { -vErrors.push(err589); -} -errors++; -} -if(data332.usage_source === undefined){ -const err590 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "usage_source"},message:"must have required property '"+"usage_source"+"'"}; -if(vErrors === null){ -vErrors = [err590]; -} -else { -vErrors.push(err590); -} -errors++; -} -if(data332.cost_source === undefined){ -const err591 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_source"},message:"must have required property '"+"cost_source"+"'"}; -if(vErrors === null){ -vErrors = [err591]; -} -else { -vErrors.push(err591); -} -errors++; -} -if(data332.tokens === undefined){ -const err592 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "tokens"},message:"must have required property '"+"tokens"+"'"}; -if(vErrors === null){ -vErrors = [err592]; -} -else { -vErrors.push(err592); -} -errors++; -} -if(data332.cost_micros === undefined){ -const err593 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "cost_micros"},message:"must have required property '"+"cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err593]; -} -else { -vErrors.push(err593); -} -errors++; -} -if(data332.elapsed_millis === undefined){ -const err594 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "elapsed_millis"},message:"must have required property '"+"elapsed_millis"+"'"}; -if(vErrors === null){ -vErrors = [err594]; -} -else { -vErrors.push(err594); -} -errors++; -} -if(data332.exhausted === undefined){ -const err595 = {instancePath:instancePath+"/questions/" + i26+"/model_call",schemaPath:"#/properties/questions/items/properties/model_call/required",keyword:"required",params:{missingProperty: "exhausted"},message:"must have required property '"+"exhausted"+"'"}; -if(vErrors === null){ -vErrors = [err595]; -} -else { -vErrors.push(err595); -} -errors++; -} -if(data332.id !== undefined){ -if(typeof data332.id !== "string"){ -const err596 = {instancePath:instancePath+"/questions/" + i26+"/model_call/id",schemaPath:"#/properties/questions/items/properties/model_call/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err596]; -} -else { -vErrors.push(err596); -} -errors++; -} -} -if(data332.logical_id !== undefined){ -if(typeof data332.logical_id !== "string"){ -const err597 = {instancePath:instancePath+"/questions/" + i26+"/model_call/logical_id",schemaPath:"#/properties/questions/items/properties/model_call/properties/logical_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err597]; -} -else { -vErrors.push(err597); -} -errors++; -} -} -if(data332.number !== undefined){ -let data335 = data332.number; -if(!((typeof data335 == "number") && (!(data335 % 1) && !isNaN(data335)))){ -const err598 = {instancePath:instancePath+"/questions/" + i26+"/model_call/number",schemaPath:"#/properties/questions/items/properties/model_call/properties/number/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err598]; -} -else { -vErrors.push(err598); -} -errors++; -} -} -if(data332.purpose !== undefined){ -if(typeof data332.purpose !== "string"){ -const err599 = {instancePath:instancePath+"/questions/" + i26+"/model_call/purpose",schemaPath:"#/properties/questions/items/properties/model_call/properties/purpose/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err599]; -} -else { -vErrors.push(err599); -} -errors++; -} -} -if(data332.usage_source !== undefined){ -if(typeof data332.usage_source !== "string"){ -const err600 = {instancePath:instancePath+"/questions/" + i26+"/model_call/usage_source",schemaPath:"#/properties/questions/items/properties/model_call/properties/usage_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err600]; -} -else { -vErrors.push(err600); -} -errors++; -} -} -if(data332.cost_source !== undefined){ -if(typeof data332.cost_source !== "string"){ -const err601 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_source",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err601]; -} -else { -vErrors.push(err601); -} -errors++; -} -} -if(data332.tokens !== undefined){ -let data339 = data332.tokens; -if(typeof data339 === "string"){ -if(!pattern0.test(data339)){ -const err602 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err602]; -} -else { -vErrors.push(err602); -} -errors++; -} -if(!(formats0.validate(data339))){ -const err603 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err603]; -} -else { -vErrors.push(err603); -} -errors++; -} -} -else { -const err604 = {instancePath:instancePath+"/questions/" + i26+"/model_call/tokens",schemaPath:"#/properties/questions/items/properties/model_call/properties/tokens/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err604]; -} -else { -vErrors.push(err604); -} -errors++; -} -} -if(data332.cost_micros !== undefined){ -let data340 = data332.cost_micros; -if(typeof data340 === "string"){ -if(!pattern0.test(data340)){ -const err605 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err605]; -} -else { -vErrors.push(err605); -} -errors++; -} -if(!(formats0.validate(data340))){ -const err606 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err606]; -} -else { -vErrors.push(err606); -} -errors++; -} -} -else { -const err607 = {instancePath:instancePath+"/questions/" + i26+"/model_call/cost_micros",schemaPath:"#/properties/questions/items/properties/model_call/properties/cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err607]; -} -else { -vErrors.push(err607); -} -errors++; -} -} -if(data332.elapsed_millis !== undefined){ -let data341 = data332.elapsed_millis; -if(typeof data341 === "string"){ -if(!pattern0.test(data341)){ -const err608 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err608]; -} -else { -vErrors.push(err608); -} -errors++; -} -if(!(formats0.validate(data341))){ -const err609 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err609]; -} -else { -vErrors.push(err609); -} -errors++; -} -} -else { -const err610 = {instancePath:instancePath+"/questions/" + i26+"/model_call/elapsed_millis",schemaPath:"#/properties/questions/items/properties/model_call/properties/elapsed_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err610]; -} -else { -vErrors.push(err610); -} -errors++; -} -} -if(data332.exhausted !== undefined){ -if(typeof data332.exhausted !== "boolean"){ -const err611 = {instancePath:instancePath+"/questions/" + i26+"/model_call/exhausted",schemaPath:"#/properties/questions/items/properties/model_call/properties/exhausted/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err611]; -} -else { -vErrors.push(err611); -} -errors++; -} -} -} -} -if(data313.acknowledged_inbox !== undefined){ -let data343 = data313.acknowledged_inbox; -if(Array.isArray(data343)){ -const len27 = data343.length; -for(let i27=0; i27<len27; i27++){ -let data344 = data343[i27]; -if(typeof data344 === "string"){ -if(!pattern0.test(data344)){ -const err612 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err612]; -} -else { -vErrors.push(err612); -} -errors++; -} -if(!(formats0.validate(data344))){ -const err613 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err613]; -} -else { -vErrors.push(err613); -} -errors++; -} -} -else { -const err614 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox/" + i27,schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err614]; -} -else { -vErrors.push(err614); -} -errors++; -} -} -} -else { -const err615 = {instancePath:instancePath+"/questions/" + i26+"/acknowledged_inbox",schemaPath:"#/properties/questions/items/properties/acknowledged_inbox/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err615]; -} -else { -vErrors.push(err615); -} -errors++; -} -} -if(data313.subscription_id !== undefined){ -if(typeof data313.subscription_id !== "string"){ -const err616 = {instancePath:instancePath+"/questions/" + i26+"/subscription_id",schemaPath:"#/properties/questions/items/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err616]; -} -else { -vErrors.push(err616); -} -errors++; -} -} -if(data313.key !== undefined){ -if(typeof data313.key !== "string"){ -const err617 = {instancePath:instancePath+"/questions/" + i26+"/key",schemaPath:"#/properties/questions/items/properties/key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err617]; -} -else { -vErrors.push(err617); -} -errors++; -} -} -if(data313.version !== undefined){ -let data347 = data313.version; -if(typeof data347 === "string"){ -if(!pattern0.test(data347)){ -const err618 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err618]; -} -else { -vErrors.push(err618); -} -errors++; -} -if(!(formats0.validate(data347))){ -const err619 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err619]; -} -else { -vErrors.push(err619); -} -errors++; -} -} -else { -const err620 = {instancePath:instancePath+"/questions/" + i26+"/version",schemaPath:"#/properties/questions/items/properties/version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err620]; -} -else { -vErrors.push(err620); -} -errors++; -} -} -if(data313.expected_version !== undefined){ -let data348 = data313.expected_version; -if(typeof data348 === "string"){ -if(!pattern0.test(data348)){ -const err621 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err621]; -} -else { -vErrors.push(err621); -} -errors++; -} -if(!(formats0.validate(data348))){ -const err622 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err622]; -} -else { -vErrors.push(err622); -} -errors++; -} -} -else { -const err623 = {instancePath:instancePath+"/questions/" + i26+"/expected_version",schemaPath:"#/properties/questions/items/properties/expected_version/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err623]; -} -else { -vErrors.push(err623); -} -errors++; -} -} -if(data313.restored !== undefined){ -let data349 = data313.restored; -if((data349 !== null) && (!(Array.isArray(data349)))){ -const err624 = {instancePath:instancePath+"/questions/" + i26+"/restored",schemaPath:"#/properties/questions/items/properties/restored/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err624]; -} -else { -vErrors.push(err624); -} -errors++; -} -if(Array.isArray(data349)){ -const len28 = data349.length; -for(let i28=0; i28<len28; i28++){ -if(typeof data349[i28] !== "string"){ -const err625 = {instancePath:instancePath+"/questions/" + i26+"/restored/" + i28,schemaPath:"#/properties/questions/items/properties/restored/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err625]; -} -else { -vErrors.push(err625); -} -errors++; -} -} -} -} -if(data313.not_restored !== undefined){ -let data351 = data313.not_restored; -if((data351 !== null) && (!(Array.isArray(data351)))){ -const err626 = {instancePath:instancePath+"/questions/" + i26+"/not_restored",schemaPath:"#/properties/questions/items/properties/not_restored/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.not_restored.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err626]; -} -else { -vErrors.push(err626); -} -errors++; -} -if(Array.isArray(data351)){ -const len29 = data351.length; -for(let i29=0; i29<len29; i29++){ -let data352 = data351[i29]; -if(data352 && typeof data352 == "object" && !Array.isArray(data352)){ -if(data352.name === undefined){ -const err627 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err627]; -} -else { -vErrors.push(err627); -} -errors++; -} -if(data352.reason === undefined){ -const err628 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err628]; -} -else { -vErrors.push(err628); -} -errors++; -} -if(data352.name !== undefined){ -if(typeof data352.name !== "string"){ -const err629 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29+"/name",schemaPath:"#/properties/questions/items/properties/not_restored/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err629]; -} -else { -vErrors.push(err629); -} -errors++; -} -} -if(data352.reason !== undefined){ -if(typeof data352.reason !== "string"){ -const err630 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29+"/reason",schemaPath:"#/properties/questions/items/properties/not_restored/items/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err630]; -} -else { -vErrors.push(err630); -} -errors++; -} -} -} -else { -const err631 = {instancePath:instancePath+"/questions/" + i26+"/not_restored/" + i29,schemaPath:"#/properties/questions/items/properties/not_restored/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err631]; -} -else { -vErrors.push(err631); -} -errors++; -} -} -} -} -if(data313.attempt !== undefined){ -if(typeof data313.attempt !== "string"){ -const err632 = {instancePath:instancePath+"/questions/" + i26+"/attempt",schemaPath:"#/properties/questions/items/properties/attempt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err632]; -} -else { -vErrors.push(err632); -} -errors++; -} -} -if(data313.budget_kind !== undefined){ -if(typeof data313.budget_kind !== "string"){ -const err633 = {instancePath:instancePath+"/questions/" + i26+"/budget_kind",schemaPath:"#/properties/questions/items/properties/budget_kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err633]; -} -else { -vErrors.push(err633); -} -errors++; -} -} -if(data313.amount !== undefined){ -let data357 = data313.amount; -if(typeof data357 === "string"){ -if(!pattern0.test(data357)){ -const err634 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err634]; -} -else { -vErrors.push(err634); -} -errors++; -} -if(!(formats0.validate(data357))){ -const err635 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err635]; -} -else { -vErrors.push(err635); -} -errors++; -} -} -else { -const err636 = {instancePath:instancePath+"/questions/" + i26+"/amount",schemaPath:"#/properties/questions/items/properties/amount/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err636]; -} -else { -vErrors.push(err636); -} -errors++; -} -} -if(data313.limit !== undefined){ -let data358 = data313.limit; -if(typeof data358 === "string"){ -if(!pattern0.test(data358)){ -const err637 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err637]; -} -else { -vErrors.push(err637); -} -errors++; -} -if(!(formats0.validate(data358))){ -const err638 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err638]; -} -else { -vErrors.push(err638); -} -errors++; -} -} -else { -const err639 = {instancePath:instancePath+"/questions/" + i26+"/limit",schemaPath:"#/properties/questions/items/properties/limit/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err639]; -} -else { -vErrors.push(err639); -} -errors++; -} -} -if(data313.used !== undefined){ -let data359 = data313.used; -if(typeof data359 === "string"){ -if(!pattern0.test(data359)){ -const err640 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err640]; -} -else { -vErrors.push(err640); -} -errors++; -} -if(!(formats0.validate(data359))){ -const err641 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err641]; -} -else { -vErrors.push(err641); -} -errors++; -} -} -else { -const err642 = {instancePath:instancePath+"/questions/" + i26+"/used",schemaPath:"#/properties/questions/items/properties/used/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err642]; -} -else { -vErrors.push(err642); -} -errors++; -} -} -if(data313.reserved !== undefined){ -let data360 = data313.reserved; -if(typeof data360 === "string"){ -if(!pattern0.test(data360)){ -const err643 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err643]; -} -else { -vErrors.push(err643); -} -errors++; -} -if(!(formats0.validate(data360))){ -const err644 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err644]; -} -else { -vErrors.push(err644); -} -errors++; -} -} -else { -const err645 = {instancePath:instancePath+"/questions/" + i26+"/reserved",schemaPath:"#/properties/questions/items/properties/reserved/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err645]; -} -else { -vErrors.push(err645); -} -errors++; -} -} -if(data313.capability_id !== undefined){ -if(typeof data313.capability_id !== "string"){ -const err646 = {instancePath:instancePath+"/questions/" + i26+"/capability_id",schemaPath:"#/properties/questions/items/properties/capability_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err646]; -} -else { -vErrors.push(err646); -} -errors++; -} -} -if(data313.generation !== undefined){ -let data362 = data313.generation; -if(typeof data362 === "string"){ -if(!pattern0.test(data362)){ -const err647 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err647]; -} -else { -vErrors.push(err647); -} -errors++; -} -if(!(formats0.validate(data362))){ -const err648 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err648]; -} -else { -vErrors.push(err648); -} -errors++; -} -} -else { -const err649 = {instancePath:instancePath+"/questions/" + i26+"/generation",schemaPath:"#/properties/questions/items/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err649]; -} -else { -vErrors.push(err649); -} -errors++; -} -} -if(data313.permission_id !== undefined){ -if(typeof data313.permission_id !== "string"){ -const err650 = {instancePath:instancePath+"/questions/" + i26+"/permission_id",schemaPath:"#/properties/questions/items/properties/permission_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err650]; -} -else { -vErrors.push(err650); -} -errors++; -} -} -if(data313.operation !== undefined){ -if(typeof data313.operation !== "string"){ -const err651 = {instancePath:instancePath+"/questions/" + i26+"/operation",schemaPath:"#/properties/questions/items/properties/operation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err651]; -} -else { -vErrors.push(err651); -} -errors++; -} -} -if(data313.canonical_path !== undefined){ -if(typeof data313.canonical_path !== "string"){ -const err652 = {instancePath:instancePath+"/questions/" + i26+"/canonical_path",schemaPath:"#/properties/questions/items/properties/canonical_path/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err652]; -} -else { -vErrors.push(err652); -} -errors++; -} -} -if(data313.request_digest !== undefined){ -if(typeof data313.request_digest !== "string"){ -const err653 = {instancePath:instancePath+"/questions/" + i26+"/request_digest",schemaPath:"#/properties/questions/items/properties/request_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err653]; -} -else { -vErrors.push(err653); -} -errors++; -} -} -if(data313.command !== undefined){ -if(typeof data313.command !== "string"){ -const err654 = {instancePath:instancePath+"/questions/" + i26+"/command",schemaPath:"#/properties/questions/items/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err654]; -} -else { -vErrors.push(err654); -} -errors++; -} -} -if(data313.rule !== undefined){ -if(typeof data313.rule !== "string"){ -const err655 = {instancePath:instancePath+"/questions/" + i26+"/rule",schemaPath:"#/properties/questions/items/properties/rule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err655]; -} -else { -vErrors.push(err655); -} -errors++; -} -} -if(data313.rule_source !== undefined){ -if(typeof data313.rule_source !== "string"){ -const err656 = {instancePath:instancePath+"/questions/" + i26+"/rule_source",schemaPath:"#/properties/questions/items/properties/rule_source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err656]; -} -else { -vErrors.push(err656); -} -errors++; -} -} -if(data313.question_id !== undefined){ -if(typeof data313.question_id !== "string"){ -const err657 = {instancePath:instancePath+"/questions/" + i26+"/question_id",schemaPath:"#/properties/questions/items/properties/question_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err657]; -} -else { -vErrors.push(err657); -} -errors++; -} -} -if(data313.question !== undefined){ -if(typeof data313.question !== "string"){ -const err658 = {instancePath:instancePath+"/questions/" + i26+"/question",schemaPath:"#/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err658]; -} -else { -vErrors.push(err658); -} -errors++; -} -} -if(data313.options !== undefined){ -let data372 = data313.options; -if((data372 !== null) && (!(Array.isArray(data372)))){ -const err659 = {instancePath:instancePath+"/questions/" + i26+"/options",schemaPath:"#/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err659]; -} -else { -vErrors.push(err659); -} -errors++; -} -if(Array.isArray(data372)){ -const len30 = data372.length; -for(let i30=0; i30<len30; i30++){ -let data373 = data372[i30]; -if(data373 && typeof data373 == "object" && !Array.isArray(data373)){ -if(data373.label === undefined){ -const err660 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30,schemaPath:"#/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err660]; -} -else { -vErrors.push(err660); -} -errors++; -} -if(data373.label !== undefined){ -if(typeof data373.label !== "string"){ -const err661 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/label",schemaPath:"#/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err661]; -} -else { -vErrors.push(err661); -} -errors++; -} -} -if(data373.description !== undefined){ -if(typeof data373.description !== "string"){ -const err662 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/description",schemaPath:"#/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err662]; -} -else { -vErrors.push(err662); -} -errors++; -} -} -if(data373.recommended !== undefined){ -if(typeof data373.recommended !== "boolean"){ -const err663 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30+"/recommended",schemaPath:"#/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err663]; -} -else { -vErrors.push(err663); -} -errors++; -} -} -} -else { -const err664 = {instancePath:instancePath+"/questions/" + i26+"/options/" + i30,schemaPath:"#/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err664]; -} -else { -vErrors.push(err664); -} -errors++; -} -} -} -} -if(data313.multiple !== undefined){ -if(typeof data313.multiple !== "boolean"){ -const err665 = {instancePath:instancePath+"/questions/" + i26+"/multiple",schemaPath:"#/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err665]; -} -else { -vErrors.push(err665); -} -errors++; -} -} -if(data313.questions !== undefined){ -let data378 = data313.questions; -if((data378 !== null) && (!(Array.isArray(data378)))){ -const err666 = {instancePath:instancePath+"/questions/" + i26+"/questions",schemaPath:"#/properties/questions/items/properties/questions/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.questions.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err666]; -} -else { -vErrors.push(err666); -} -errors++; -} -if(Array.isArray(data378)){ -const len31 = data378.length; -for(let i31=0; i31<len31; i31++){ -let data379 = data378[i31]; -if(data379 && typeof data379 == "object" && !Array.isArray(data379)){ -if(data379.question === undefined){ -const err667 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31,schemaPath:"#/properties/questions/items/properties/questions/items/required",keyword:"required",params:{missingProperty: "question"},message:"must have required property '"+"question"+"'"}; -if(vErrors === null){ -vErrors = [err667]; -} -else { -vErrors.push(err667); -} -errors++; -} -if(data379.question !== undefined){ -if(typeof data379.question !== "string"){ -const err668 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/question",schemaPath:"#/properties/questions/items/properties/questions/items/properties/question/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err668]; -} -else { -vErrors.push(err668); -} -errors++; -} -} -if(data379.options !== undefined){ -let data381 = data379.options; -if((data381 !== null) && (!(Array.isArray(data381)))){ -const err669 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.questions.items.properties.options.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err669]; -} -else { -vErrors.push(err669); -} -errors++; -} -if(Array.isArray(data381)){ -const len32 = data381.length; -for(let i32=0; i32<len32; i32++){ -let data382 = data381[i32]; -if(data382 && typeof data382 == "object" && !Array.isArray(data382)){ -if(data382.label === undefined){ -const err670 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32,schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err670]; -} -else { -vErrors.push(err670); -} -errors++; -} -if(data382.label !== undefined){ -if(typeof data382.label !== "string"){ -const err671 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/label",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err671]; -} -else { -vErrors.push(err671); -} -errors++; -} -} -if(data382.description !== undefined){ -if(typeof data382.description !== "string"){ -const err672 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/description",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err672]; -} -else { -vErrors.push(err672); -} -errors++; -} -} -if(data382.recommended !== undefined){ -if(typeof data382.recommended !== "boolean"){ -const err673 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32+"/recommended",schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/properties/recommended/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err673]; -} -else { -vErrors.push(err673); -} -errors++; -} -} -} -else { -const err674 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/options/" + i32,schemaPath:"#/properties/questions/items/properties/questions/items/properties/options/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err674]; -} -else { -vErrors.push(err674); -} -errors++; -} -} -} -} -if(data379.multiple !== undefined){ -if(typeof data379.multiple !== "boolean"){ -const err675 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31+"/multiple",schemaPath:"#/properties/questions/items/properties/questions/items/properties/multiple/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err675]; -} -else { -vErrors.push(err675); -} -errors++; -} -} -} -else { -const err676 = {instancePath:instancePath+"/questions/" + i26+"/questions/" + i31,schemaPath:"#/properties/questions/items/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err676]; -} -else { -vErrors.push(err676); -} -errors++; -} -} -} -} -if(data313.answer !== undefined){ -let data387 = data313.answer; -if((data387 !== null) && (!(Array.isArray(data387)))){ -const err677 = {instancePath:instancePath+"/questions/" + i26+"/answer",schemaPath:"#/properties/questions/items/properties/answer/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err677]; -} -else { -vErrors.push(err677); -} -errors++; -} -if(Array.isArray(data387)){ -const len33 = data387.length; -for(let i33=0; i33<len33; i33++){ -if(typeof data387[i33] !== "string"){ -const err678 = {instancePath:instancePath+"/questions/" + i26+"/answer/" + i33,schemaPath:"#/properties/questions/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err678]; -} -else { -vErrors.push(err678); -} -errors++; -} -} -} -} -if(data313.dismissed !== undefined){ -if(typeof data313.dismissed !== "boolean"){ -const err679 = {instancePath:instancePath+"/questions/" + i26+"/dismissed",schemaPath:"#/properties/questions/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err679]; -} -else { -vErrors.push(err679); -} -errors++; -} -} -if(data313.answers !== undefined){ -let data390 = data313.answers; -if((data390 !== null) && (!(Array.isArray(data390)))){ -const err680 = {instancePath:instancePath+"/questions/" + i26+"/answers",schemaPath:"#/properties/questions/items/properties/answers/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err680]; -} -else { -vErrors.push(err680); -} -errors++; -} -if(Array.isArray(data390)){ -const len34 = data390.length; -for(let i34=0; i34<len34; i34++){ -let data391 = data390[i34]; -if(data391 && typeof data391 == "object" && !Array.isArray(data391)){ -if(data391.answer !== undefined){ -let data392 = data391.answer; -if((data392 !== null) && (!(Array.isArray(data392)))){ -const err681 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/answer",schemaPath:"#/properties/questions/items/properties/answers/items/properties/answer/type",keyword:"type",params:{type: schema160.properties.questions.items.properties.answers.items.properties.answer.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err681]; -} -else { -vErrors.push(err681); -} -errors++; -} -if(Array.isArray(data392)){ -const len35 = data392.length; -for(let i35=0; i35<len35; i35++){ -if(typeof data392[i35] !== "string"){ -const err682 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/answer/" + i35,schemaPath:"#/properties/questions/items/properties/answers/items/properties/answer/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err682]; -} -else { -vErrors.push(err682); -} -errors++; -} -} -} -} -if(data391.dismissed !== undefined){ -if(typeof data391.dismissed !== "boolean"){ -const err683 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34+"/dismissed",schemaPath:"#/properties/questions/items/properties/answers/items/properties/dismissed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err683]; -} -else { -vErrors.push(err683); -} -errors++; -} -} -} -else { -const err684 = {instancePath:instancePath+"/questions/" + i26+"/answers/" + i34,schemaPath:"#/properties/questions/items/properties/answers/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err684]; -} -else { -vErrors.push(err684); -} -errors++; -} -} -} -} -} -else { -const err685 = {instancePath:instancePath+"/questions/" + i26,schemaPath:"#/properties/questions/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err685]; -} -else { -vErrors.push(err685); -} -errors++; -} -} -} -} -if(data.permission_mode !== undefined){ -if(typeof data.permission_mode !== "string"){ -const err686 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err686]; -} -else { -vErrors.push(err686); -} -errors++; -} -} -} -else { -const err687 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err687]; -} -else { -vErrors.push(err687); -} -errors++; -} -validate159.errors = vErrors; -return errors === 0; -} - -export const RunConfigureParams = validate160; -const schema161 = {"type":"object","properties":{"system":{"type":"string"},"max_turns":{"type":"integer"},"headless":{"type":"boolean"},"cache_key":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/RunConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"RunConfigureParams","additionalProperties":true}; - -function validate160(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RunConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.system !== undefined){ -if(typeof data.system !== "string"){ -const err0 = {instancePath:instancePath+"/system",schemaPath:"#/properties/system/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.max_turns !== undefined){ -let data1 = data.max_turns; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err1 = {instancePath:instancePath+"/max_turns",schemaPath:"#/properties/max_turns/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.headless !== undefined){ -if(typeof data.headless !== "boolean"){ -const err2 = {instancePath:instancePath+"/headless",schemaPath:"#/properties/headless/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cache_key !== undefined){ -if(typeof data.cache_key !== "string"){ -const err3 = {instancePath:instancePath+"/cache_key",schemaPath:"#/properties/cache_key/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate160.errors = vErrors; -return errors === 0; -} - -export const RuntimeConfiguration = validate161; -const schema162 = {"type":"object","properties":{"default_execution_engine":{"type":"string"},"disabled_providers":{"type":["null","array"],"items":{"type":"string"}},"discovery":{"type":["null","object"],"properties":{"status":{"type":"string"},"message":{"type":"string"},"model_count":{"type":"integer"}},"required":["status"],"additionalProperties":true},"remote_hosts":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"runtime_id":{"type":"string"},"connect_on_launch":{"type":"boolean"}},"required":["id","name","url","runtime_id","connect_on_launch"],"additionalProperties":true}},"import_claude":{"type":"boolean"},"import_codex":{"type":"boolean"},"mcp_import_offered":{"type":"boolean"},"brand_icons":{"type":"boolean"},"revision":{"type":"string"},"default_model":{"type":"string"},"default_provider":{"type":"string"},"default_effort":{"type":"string"},"default_permission_mode":{"type":"string"},"compact_model":{"type":"string"},"compact_provider":{"type":"string"},"compact_percent":{"type":"integer"},"goal_max_rounds":{"type":"integer"},"max_retries":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/RuntimeConfiguration","$schema":"http://json-schema.org/draft-07/schema#","title":"RuntimeConfiguration","required":["default_execution_engine","import_claude","import_codex","mcp_import_offered","brand_icons","revision","default_model","default_provider","default_effort","compact_model","compact_provider","compact_percent","goal_max_rounds","max_retries"],"additionalProperties":true}; - -function validate161(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/RuntimeConfiguration" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.default_execution_engine === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_execution_engine"},message:"must have required property '"+"default_execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.import_claude === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "import_claude"},message:"must have required property '"+"import_claude"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.import_codex === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "import_codex"},message:"must have required property '"+"import_codex"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.mcp_import_offered === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "mcp_import_offered"},message:"must have required property '"+"mcp_import_offered"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.brand_icons === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "brand_icons"},message:"must have required property '"+"brand_icons"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.revision === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.default_model === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_model"},message:"must have required property '"+"default_model"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.default_provider === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_provider"},message:"must have required property '"+"default_provider"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.default_effort === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "default_effort"},message:"must have required property '"+"default_effort"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.compact_model === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_model"},message:"must have required property '"+"compact_model"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.compact_provider === undefined){ -const err10 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_provider"},message:"must have required property '"+"compact_provider"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data.compact_percent === undefined){ -const err11 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "compact_percent"},message:"must have required property '"+"compact_percent"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data.goal_max_rounds === undefined){ -const err12 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "goal_max_rounds"},message:"must have required property '"+"goal_max_rounds"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data.max_retries === undefined){ -const err13 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_retries"},message:"must have required property '"+"max_retries"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data.default_execution_engine !== undefined){ -if(typeof data.default_execution_engine !== "string"){ -const err14 = {instancePath:instancePath+"/default_execution_engine",schemaPath:"#/properties/default_execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.disabled_providers !== undefined){ -let data1 = data.disabled_providers; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err15 = {instancePath:instancePath+"/disabled_providers",schemaPath:"#/properties/disabled_providers/type",keyword:"type",params:{type: schema162.properties.disabled_providers.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data1[i0] !== "string"){ -const err16 = {instancePath:instancePath+"/disabled_providers/" + i0,schemaPath:"#/properties/disabled_providers/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -} -} -if(data.discovery !== undefined){ -let data3 = data.discovery; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err17 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/type",keyword:"type",params:{type: schema162.properties.discovery.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.status === undefined){ -const err18 = {instancePath:instancePath+"/discovery",schemaPath:"#/properties/discovery/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data3.status !== undefined){ -if(typeof data3.status !== "string"){ -const err19 = {instancePath:instancePath+"/discovery/status",schemaPath:"#/properties/discovery/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data3.message !== undefined){ -if(typeof data3.message !== "string"){ -const err20 = {instancePath:instancePath+"/discovery/message",schemaPath:"#/properties/discovery/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data3.model_count !== undefined){ -let data6 = data3.model_count; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err21 = {instancePath:instancePath+"/discovery/model_count",schemaPath:"#/properties/discovery/properties/model_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -} -} -if(data.remote_hosts !== undefined){ -let data7 = data.remote_hosts; -if((data7 !== null) && (!(Array.isArray(data7)))){ -const err22 = {instancePath:instancePath+"/remote_hosts",schemaPath:"#/properties/remote_hosts/type",keyword:"type",params:{type: schema162.properties.remote_hosts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(Array.isArray(data7)){ -const len1 = data7.length; -for(let i1=0; i1<len1; i1++){ -let data8 = data7[i1]; -if(data8 && typeof data8 == "object" && !Array.isArray(data8)){ -if(data8.id === undefined){ -const err23 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(data8.name === undefined){ -const err24 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(data8.url === undefined){ -const err25 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(data8.runtime_id === undefined){ -const err26 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "runtime_id"},message:"must have required property '"+"runtime_id"+"'"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(data8.connect_on_launch === undefined){ -const err27 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/required",keyword:"required",params:{missingProperty: "connect_on_launch"},message:"must have required property '"+"connect_on_launch"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data8.id !== undefined){ -if(typeof data8.id !== "string"){ -const err28 = {instancePath:instancePath+"/remote_hosts/" + i1+"/id",schemaPath:"#/properties/remote_hosts/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data8.name !== undefined){ -if(typeof data8.name !== "string"){ -const err29 = {instancePath:instancePath+"/remote_hosts/" + i1+"/name",schemaPath:"#/properties/remote_hosts/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data8.url !== undefined){ -if(typeof data8.url !== "string"){ -const err30 = {instancePath:instancePath+"/remote_hosts/" + i1+"/url",schemaPath:"#/properties/remote_hosts/items/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data8.runtime_id !== undefined){ -if(typeof data8.runtime_id !== "string"){ -const err31 = {instancePath:instancePath+"/remote_hosts/" + i1+"/runtime_id",schemaPath:"#/properties/remote_hosts/items/properties/runtime_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data8.connect_on_launch !== undefined){ -if(typeof data8.connect_on_launch !== "boolean"){ -const err32 = {instancePath:instancePath+"/remote_hosts/" + i1+"/connect_on_launch",schemaPath:"#/properties/remote_hosts/items/properties/connect_on_launch/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath:instancePath+"/remote_hosts/" + i1,schemaPath:"#/properties/remote_hosts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -} -} -if(data.import_claude !== undefined){ -if(typeof data.import_claude !== "boolean"){ -const err34 = {instancePath:instancePath+"/import_claude",schemaPath:"#/properties/import_claude/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data.import_codex !== undefined){ -if(typeof data.import_codex !== "boolean"){ -const err35 = {instancePath:instancePath+"/import_codex",schemaPath:"#/properties/import_codex/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data.mcp_import_offered !== undefined){ -if(typeof data.mcp_import_offered !== "boolean"){ -const err36 = {instancePath:instancePath+"/mcp_import_offered",schemaPath:"#/properties/mcp_import_offered/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data.brand_icons !== undefined){ -if(typeof data.brand_icons !== "boolean"){ -const err37 = {instancePath:instancePath+"/brand_icons",schemaPath:"#/properties/brand_icons/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err38 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data.default_model !== undefined){ -if(typeof data.default_model !== "string"){ -const err39 = {instancePath:instancePath+"/default_model",schemaPath:"#/properties/default_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data.default_provider !== undefined){ -if(typeof data.default_provider !== "string"){ -const err40 = {instancePath:instancePath+"/default_provider",schemaPath:"#/properties/default_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data.default_effort !== undefined){ -if(typeof data.default_effort !== "string"){ -const err41 = {instancePath:instancePath+"/default_effort",schemaPath:"#/properties/default_effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data.default_permission_mode !== undefined){ -if(typeof data.default_permission_mode !== "string"){ -const err42 = {instancePath:instancePath+"/default_permission_mode",schemaPath:"#/properties/default_permission_mode/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -if(data.compact_model !== undefined){ -if(typeof data.compact_model !== "string"){ -const err43 = {instancePath:instancePath+"/compact_model",schemaPath:"#/properties/compact_model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data.compact_provider !== undefined){ -if(typeof data.compact_provider !== "string"){ -const err44 = {instancePath:instancePath+"/compact_provider",schemaPath:"#/properties/compact_provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -} -if(data.compact_percent !== undefined){ -let data25 = data.compact_percent; -if(!((typeof data25 == "number") && (!(data25 % 1) && !isNaN(data25)))){ -const err45 = {instancePath:instancePath+"/compact_percent",schemaPath:"#/properties/compact_percent/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -if(data.goal_max_rounds !== undefined){ -let data26 = data.goal_max_rounds; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err46 = {instancePath:instancePath+"/goal_max_rounds",schemaPath:"#/properties/goal_max_rounds/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data.max_retries !== undefined){ -let data27 = data.max_retries; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err47 = {instancePath:instancePath+"/max_retries",schemaPath:"#/properties/max_retries/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -} -} -else { -const err48 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -validate161.errors = vErrors; -return errors === 0; -} - -export const ScheduleCreateParams = validate162; -const schema163 = {"type":"object","properties":{"schedule":{"type":"string"},"prompt":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ScheduleCreateParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleCreateParams","required":["schedule","prompt"],"additionalProperties":true}; - -function validate162(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleCreateParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.prompt === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.schedule !== undefined){ -if(typeof data.schedule !== "string"){ -const err2 = {instancePath:instancePath+"/schedule",schemaPath:"#/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.prompt !== undefined){ -if(typeof data.prompt !== "string"){ -const err3 = {instancePath:instancePath+"/prompt",schemaPath:"#/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -} -else { -const err4 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -validate162.errors = vErrors; -return errors === 0; -} - -export const ScheduleDeleteParams = validate163; -const schema164 = {"type":"object","properties":{"schedule_id":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ScheduleDeleteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleDeleteParams","required":["schedule_id"],"additionalProperties":true}; - -function validate163(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleDeleteParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule_id"},message:"must have required property '"+"schedule_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.schedule_id !== undefined){ -let data0 = data.schedule_id; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err1 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate163.errors = vErrors; -return errors === 0; -} - -export const ScheduleListResult = validate164; -const schema165 = {"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"integer"},"schedule":{"type":"string"},"prompt":{"type":"string"},"anchor":{"type":"string"},"last_fire":{"type":"string"}},"required":["id","schedule","prompt","anchor","last_fire"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/ScheduleListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleListResult"}; - -function validate164(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema165.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.id === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.schedule === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "schedule"},message:"must have required property '"+"schedule"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.prompt === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "prompt"},message:"must have required property '"+"prompt"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.anchor === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "anchor"},message:"must have required property '"+"anchor"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.last_fire === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "last_fire"},message:"must have required property '"+"last_fire"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.id !== undefined){ -let data1 = data0.id; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err6 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.schedule !== undefined){ -if(typeof data0.schedule !== "string"){ -const err7 = {instancePath:instancePath+"/" + i0+"/schedule",schemaPath:"#/items/properties/schedule/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.prompt !== undefined){ -if(typeof data0.prompt !== "string"){ -const err8 = {instancePath:instancePath+"/" + i0+"/prompt",schemaPath:"#/items/properties/prompt/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data0.anchor !== undefined){ -if(typeof data0.anchor !== "string"){ -const err9 = {instancePath:instancePath+"/" + i0+"/anchor",schemaPath:"#/items/properties/anchor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data0.last_fire !== undefined){ -if(typeof data0.last_fire !== "string"){ -const err10 = {instancePath:instancePath+"/" + i0+"/last_fire",schemaPath:"#/items/properties/last_fire/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -validate164.errors = vErrors; -return errors === 0; -} - -export const ScheduleResult = validate165; -const schema166 = {"type":"object","properties":{"schedule_id":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/ScheduleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ScheduleResult","required":["schedule_id"],"additionalProperties":true}; - -function validate165(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ScheduleResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.schedule_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "schedule_id"},message:"must have required property '"+"schedule_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.schedule_id !== undefined){ -let data0 = data.schedule_id; -if(!((typeof data0 == "number") && (!(data0 % 1) && !isNaN(data0)))){ -const err1 = {instancePath:instancePath+"/schedule_id",schemaPath:"#/properties/schedule_id/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate165.errors = vErrors; -return errors === 0; -} - -export const SessionCatalogPage = validate166; -const schema167 = {"type":"object","properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"items":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"workspace_id":{"type":"string"},"pinned":{"type":"boolean"},"archived":{"type":"boolean"},"updated_at":{"type":"string"},"truncated":{"type":"boolean"}},"required":["id","kind","title","model","provider","cwd","pinned","archived","updated_at","truncated"],"additionalProperties":true}},"next_cursor":{"type":["null","object"],"properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]}},"required":["revision","offset","status"],"additionalProperties":true},"has_more":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/SessionCatalogPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionCatalogPage","required":["revision","items","has_more"],"additionalProperties":true}; - -function validate166(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionCatalogPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.revision === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.has_more === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.revision !== undefined){ -let data0 = data.revision; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err3 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err4 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.items !== undefined){ -let data1 = data.items; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err6 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: schema167.properties.items.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.kind === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.title === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.model === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.provider === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.cwd === undefined){ -const err12 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.pinned === undefined){ -const err13 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.archived === undefined){ -const err14 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.updated_at === undefined){ -const err15 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.truncated === undefined){ -const err16 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/id",schemaPath:"#/properties/items/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/kind",schemaPath:"#/properties/items/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data2.title !== undefined){ -if(typeof data2.title !== "string"){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data2.model !== undefined){ -if(typeof data2.model !== "string"){ -const err20 = {instancePath:instancePath+"/items/" + i0+"/model",schemaPath:"#/properties/items/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data2.provider !== undefined){ -if(typeof data2.provider !== "string"){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/provider",schemaPath:"#/properties/items/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.cwd !== undefined){ -if(typeof data2.cwd !== "string"){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/cwd",schemaPath:"#/properties/items/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.workspace_id !== undefined){ -if(typeof data2.workspace_id !== "string"){ -const err23 = {instancePath:instancePath+"/items/" + i0+"/workspace_id",schemaPath:"#/properties/items/items/properties/workspace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.pinned !== undefined){ -if(typeof data2.pinned !== "boolean"){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/pinned",schemaPath:"#/properties/items/items/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.archived !== undefined){ -if(typeof data2.archived !== "boolean"){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/archived",schemaPath:"#/properties/items/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.updated_at !== undefined){ -if(typeof data2.updated_at !== "string"){ -const err26 = {instancePath:instancePath+"/items/" + i0+"/updated_at",schemaPath:"#/properties/items/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data2.truncated !== undefined){ -if(typeof data2.truncated !== "boolean"){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -else { -const err28 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -} -} -if(data.next_cursor !== undefined){ -let data14 = data.next_cursor; -if((data14 !== null) && (!(data14 && typeof data14 == "object" && !Array.isArray(data14)))){ -const err29 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/type",keyword:"type",params:{type: schema167.properties.next_cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(data14 && typeof data14 == "object" && !Array.isArray(data14)){ -if(data14.revision === undefined){ -const err30 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -if(data14.offset === undefined){ -const err31 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data14.status === undefined){ -const err32 = {instancePath:instancePath+"/next_cursor",schemaPath:"#/properties/next_cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data14.revision !== undefined){ -let data15 = data14.revision; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err33 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err34 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -else { -const err35 = {instancePath:instancePath+"/next_cursor/revision",schemaPath:"#/properties/next_cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data14.offset !== undefined){ -let data16 = data14.offset; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err36 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err37 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -else { -const err38 = {instancePath:instancePath+"/next_cursor/offset",schemaPath:"#/properties/next_cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data14.search !== undefined){ -if(typeof data14.search !== "string"){ -const err39 = {instancePath:instancePath+"/next_cursor/search",schemaPath:"#/properties/next_cursor/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data14.status !== undefined){ -let data18 = data14.status; -if(typeof data18 !== "string"){ -const err40 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(((data18 === "active") || (data18 === "archived")) || (data18 === "all"))){ -const err41 = {instancePath:instancePath+"/next_cursor/status",schemaPath:"#/properties/next_cursor/properties/status/enum",keyword:"enum",params:{allowedValues: schema167.properties.next_cursor.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err42 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -else { -const err43 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -validate166.errors = vErrors; -return errors === 0; -} - -export const SessionCatalogParams = validate167; -const schema168 = {"type":"object","properties":{"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]},"cursor":{"type":["null","object"],"properties":{"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"search":{"type":"string"},"status":{"type":"string","enum":["active","archived","all"]}},"required":["revision","offset","status"],"additionalProperties":true},"limit":{"type":"integer"},"max_bytes":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/SessionCatalogParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionCatalogParams","required":["limit","max_bytes"],"additionalProperties":true}; - -function validate167(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionCatalogParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.limit === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "limit"},message:"must have required property '"+"limit"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.max_bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "max_bytes"},message:"must have required property '"+"max_bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.search !== undefined){ -if(typeof data.search !== "string"){ -const err2 = {instancePath:instancePath+"/search",schemaPath:"#/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.status !== undefined){ -let data1 = data.status; -if(typeof data1 !== "string"){ -const err3 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(((data1 === "active") || (data1 === "archived")) || (data1 === "all"))){ -const err4 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/enum",keyword:"enum",params:{allowedValues: schema168.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: schema168.properties.cursor.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.revision === undefined){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2.offset === undefined){ -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.status === undefined){ -const err8 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.revision !== undefined){ -let data3 = data2.revision; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err9 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err10 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -else { -const err11 = {instancePath:instancePath+"/cursor/revision",schemaPath:"#/properties/cursor/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data2.offset !== undefined){ -let data4 = data2.offset; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err12 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err13 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -else { -const err14 = {instancePath:instancePath+"/cursor/offset",schemaPath:"#/properties/cursor/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data2.search !== undefined){ -if(typeof data2.search !== "string"){ -const err15 = {instancePath:instancePath+"/cursor/search",schemaPath:"#/properties/cursor/properties/search/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data2.status !== undefined){ -let data6 = data2.status; -if(typeof data6 !== "string"){ -const err16 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(!(((data6 === "active") || (data6 === "archived")) || (data6 === "all"))){ -const err17 = {instancePath:instancePath+"/cursor/status",schemaPath:"#/properties/cursor/properties/status/enum",keyword:"enum",params:{allowedValues: schema168.properties.cursor.properties.status.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -} -} -if(data.limit !== undefined){ -let data7 = data.limit; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err18 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.max_bytes !== undefined){ -let data8 = data.max_bytes; -if(!((typeof data8 == "number") && (!(data8 % 1) && !isNaN(data8)))){ -const err19 = {instancePath:instancePath+"/max_bytes",schemaPath:"#/properties/max_bytes/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -} -else { -const err20 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -validate167.errors = vErrors; -return errors === 0; -} - -export const SessionListResult = validate168; -const schema169 = {"type":["null","array"],"items":{"type":"object","properties":{"execution_engine":{"type":"string"},"definition":{"type":"string"},"definition_revision":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"cwd":{"type":"string"},"goal":{"type":"string"},"forked_from":{"type":"string"},"fork_seq":{"type":"integer"},"tags":{"type":["null","array"],"items":{"type":"string"}},"archived":{"type":"boolean"},"pinned":{"type":"boolean"},"effort":{"type":"string"},"usage_in":{"type":"integer"},"usage_cached":{"type":"integer"},"usage_out":{"type":"integer"},"updated_at":{"type":"string"}},"required":["execution_engine","definition","definition_revision","id","kind","title","model","provider","cwd","goal","forked_from","fork_seq","tags","archived","pinned","effort","usage_in","usage_cached","usage_out","updated_at"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/SessionListResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionListResult"}; - -function validate168(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionListResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema169.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.execution_engine === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "execution_engine"},message:"must have required property '"+"execution_engine"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.definition === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.definition_revision === undefined){ -const err3 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "definition_revision"},message:"must have required property '"+"definition_revision"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.id === undefined){ -const err4 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.kind === undefined){ -const err5 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.title === undefined){ -const err6 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data0.model === undefined){ -const err7 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "model"},message:"must have required property '"+"model"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data0.provider === undefined){ -const err8 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "provider"},message:"must have required property '"+"provider"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data0.cwd === undefined){ -const err9 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data0.goal === undefined){ -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "goal"},message:"must have required property '"+"goal"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data0.forked_from === undefined){ -const err11 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "forked_from"},message:"must have required property '"+"forked_from"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data0.fork_seq === undefined){ -const err12 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "fork_seq"},message:"must have required property '"+"fork_seq"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data0.tags === undefined){ -const err13 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "tags"},message:"must have required property '"+"tags"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data0.archived === undefined){ -const err14 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data0.pinned === undefined){ -const err15 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "pinned"},message:"must have required property '"+"pinned"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data0.effort === undefined){ -const err16 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "effort"},message:"must have required property '"+"effort"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data0.usage_in === undefined){ -const err17 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_in"},message:"must have required property '"+"usage_in"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data0.usage_cached === undefined){ -const err18 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_cached"},message:"must have required property '"+"usage_cached"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data0.usage_out === undefined){ -const err19 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "usage_out"},message:"must have required property '"+"usage_out"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data0.updated_at === undefined){ -const err20 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "updated_at"},message:"must have required property '"+"updated_at"+"'"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data0.execution_engine !== undefined){ -if(typeof data0.execution_engine !== "string"){ -const err21 = {instancePath:instancePath+"/" + i0+"/execution_engine",schemaPath:"#/items/properties/execution_engine/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data0.definition !== undefined){ -if(typeof data0.definition !== "string"){ -const err22 = {instancePath:instancePath+"/" + i0+"/definition",schemaPath:"#/items/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data0.definition_revision !== undefined){ -if(typeof data0.definition_revision !== "string"){ -const err23 = {instancePath:instancePath+"/" + i0+"/definition_revision",schemaPath:"#/items/properties/definition_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data0.id !== undefined){ -if(typeof data0.id !== "string"){ -const err24 = {instancePath:instancePath+"/" + i0+"/id",schemaPath:"#/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data0.kind !== undefined){ -if(typeof data0.kind !== "string"){ -const err25 = {instancePath:instancePath+"/" + i0+"/kind",schemaPath:"#/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data0.title !== undefined){ -if(typeof data0.title !== "string"){ -const err26 = {instancePath:instancePath+"/" + i0+"/title",schemaPath:"#/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data0.model !== undefined){ -if(typeof data0.model !== "string"){ -const err27 = {instancePath:instancePath+"/" + i0+"/model",schemaPath:"#/items/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -if(data0.provider !== undefined){ -if(typeof data0.provider !== "string"){ -const err28 = {instancePath:instancePath+"/" + i0+"/provider",schemaPath:"#/items/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data0.cwd !== undefined){ -if(typeof data0.cwd !== "string"){ -const err29 = {instancePath:instancePath+"/" + i0+"/cwd",schemaPath:"#/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data0.goal !== undefined){ -if(typeof data0.goal !== "string"){ -const err30 = {instancePath:instancePath+"/" + i0+"/goal",schemaPath:"#/items/properties/goal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data0.forked_from !== undefined){ -if(typeof data0.forked_from !== "string"){ -const err31 = {instancePath:instancePath+"/" + i0+"/forked_from",schemaPath:"#/items/properties/forked_from/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data0.fork_seq !== undefined){ -let data12 = data0.fork_seq; -if(!((typeof data12 == "number") && (!(data12 % 1) && !isNaN(data12)))){ -const err32 = {instancePath:instancePath+"/" + i0+"/fork_seq",schemaPath:"#/items/properties/fork_seq/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -if(data0.tags !== undefined){ -let data13 = data0.tags; -if((data13 !== null) && (!(Array.isArray(data13)))){ -const err33 = {instancePath:instancePath+"/" + i0+"/tags",schemaPath:"#/items/properties/tags/type",keyword:"type",params:{type: schema169.items.properties.tags.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(Array.isArray(data13)){ -const len1 = data13.length; -for(let i1=0; i1<len1; i1++){ -if(typeof data13[i1] !== "string"){ -const err34 = {instancePath:instancePath+"/" + i0+"/tags/" + i1,schemaPath:"#/items/properties/tags/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -} -if(data0.archived !== undefined){ -if(typeof data0.archived !== "boolean"){ -const err35 = {instancePath:instancePath+"/" + i0+"/archived",schemaPath:"#/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data0.pinned !== undefined){ -if(typeof data0.pinned !== "boolean"){ -const err36 = {instancePath:instancePath+"/" + i0+"/pinned",schemaPath:"#/items/properties/pinned/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -if(data0.effort !== undefined){ -if(typeof data0.effort !== "string"){ -const err37 = {instancePath:instancePath+"/" + i0+"/effort",schemaPath:"#/items/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data0.usage_in !== undefined){ -let data18 = data0.usage_in; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err38 = {instancePath:instancePath+"/" + i0+"/usage_in",schemaPath:"#/items/properties/usage_in/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data0.usage_cached !== undefined){ -let data19 = data0.usage_cached; -if(!((typeof data19 == "number") && (!(data19 % 1) && !isNaN(data19)))){ -const err39 = {instancePath:instancePath+"/" + i0+"/usage_cached",schemaPath:"#/items/properties/usage_cached/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data0.usage_out !== undefined){ -let data20 = data0.usage_out; -if(!((typeof data20 == "number") && (!(data20 % 1) && !isNaN(data20)))){ -const err40 = {instancePath:instancePath+"/" + i0+"/usage_out",schemaPath:"#/items/properties/usage_out/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data0.updated_at !== undefined){ -if(typeof data0.updated_at !== "string"){ -const err41 = {instancePath:instancePath+"/" + i0+"/updated_at",schemaPath:"#/items/properties/updated_at/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -} -else { -const err42 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -validate168.errors = vErrors; -return errors === 0; -} - -export const SessionMetadata = validate169; -const schema170 = {"type":"object","properties":{"root_id":{"type":"string"},"title":{"type":"string"},"cwd":{"type":"string"},"history_revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"archived":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/SessionMetadata","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionMetadata","required":["root_id","title","cwd","history_revision","archived"],"additionalProperties":true}; - -function validate169(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionMetadata" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.title === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cwd === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.history_revision === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "history_revision"},message:"must have required property '"+"history_revision"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.archived === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err6 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err7 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.history_revision !== undefined){ -let data3 = data.history_revision; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err8 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err9 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/history_revision",schemaPath:"#/properties/history_revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.archived !== undefined){ -if(typeof data.archived !== "boolean"){ -const err11 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -else { -const err12 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -validate169.errors = vErrors; -return errors === 0; -} - -export const SessionPreviewResult = validate170; -const schema171 = {"type":"object","properties":{"root_id":{"type":"string"},"user":{"type":"string"},"assistant":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionPreviewResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionPreviewResult","required":["root_id","user","assistant"],"additionalProperties":true}; - -function validate170(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionPreviewResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.user === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "user"},message:"must have required property '"+"user"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.assistant === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "assistant"},message:"must have required property '"+"assistant"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.user !== undefined){ -if(typeof data.user !== "string"){ -const err4 = {instancePath:instancePath+"/user",schemaPath:"#/properties/user/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.assistant !== undefined){ -if(typeof data.assistant !== "string"){ -const err5 = {instancePath:instancePath+"/assistant",schemaPath:"#/properties/assistant/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate170.errors = vErrors; -return errors === 0; -} - -export const SessionSummariesParams = validate171; -const schema172 = {"type":"object","properties":{"root_ids":{"type":"array","items":{"type":"string","pattern":"^[\\s\\S]{1,256}$"},"maxItems":32,"uniqueItems":true}},"$id":"https://whip.dev/protocol/v6/SessionSummariesParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionSummariesParams","required":["root_ids"],"additionalProperties":true}; -const pattern205 = new RegExp("^[\\s\\S]{1,256}$", "u"); - -function validate171(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionSummariesParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_ids === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_ids"},message:"must have required property '"+"root_ids"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_ids !== undefined){ -let data0 = data.root_ids; -if(Array.isArray(data0)){ -if(data0.length > 32){ -const err1 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/maxItems",keyword:"maxItems",params:{limit: 32},message:"must NOT have more than 32 items"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(typeof data1 === "string"){ -if(!pattern205.test(data1)){ -const err2 = {instancePath:instancePath+"/root_ids/" + i0,schemaPath:"#/properties/root_ids/items/pattern",keyword:"pattern",params:{pattern: "^[\\s\\S]{1,256}$"},message:"must match pattern \""+"^[\\s\\S]{1,256}$"+"\""}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -else { -const err3 = {instancePath:instancePath+"/root_ids/" + i0,schemaPath:"#/properties/root_ids/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -let i1 = data0.length; -let j0; -if(i1 > 1){ -const indices0 = {}; -for(;i1--;){ -let item0 = data0[i1]; -if(typeof item0 !== "string"){ -continue; -} -if(typeof indices0[item0] == "number"){ -j0 = indices0[item0]; -const err4 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/uniqueItems",keyword:"uniqueItems",params:{i: i1, j: j0},message:"must NOT have duplicate items (items ## "+j0+" and "+i1+" are identical)"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -break; -} -indices0[item0] = i1; -} -} -} -else { -const err5 = {instancePath:instancePath+"/root_ids",schemaPath:"#/properties/root_ids/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate171.errors = vErrors; -return errors === 0; -} - -export const SessionSummariesResult = validate172; -const schema173 = {"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"root_id":{"type":"string"},"missing":{"type":"boolean"},"archived":{"type":"boolean"},"title":{"type":"string"},"cwd":{"type":"string"},"workspace_id":{"type":"string"},"running_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"queued_agents":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_permissions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_questions":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"truncated":{"type":"boolean"}},"required":["root_id","missing","archived","title","cwd","running_agents","queued_agents","pending_permissions","pending_questions","truncated"],"additionalProperties":true},"maxItems":32}},"$id":"https://whip.dev/protocol/v6/SessionSummariesResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionSummariesResult","required":["items"],"additionalProperties":true}; - -function validate172(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionSummariesResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.items === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "items"},message:"must have required property '"+"items"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.items !== undefined){ -let data0 = data.items; -if(Array.isArray(data0)){ -if(data0.length > 32){ -const err1 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/maxItems",keyword:"maxItems",params:{limit: 32},message:"must NOT have more than 32 items"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -const len0 = data0.length; -for(let i0=0; i0<len0; i0++){ -let data1 = data0[i0]; -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.root_id === undefined){ -const err2 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data1.missing === undefined){ -const err3 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "missing"},message:"must have required property '"+"missing"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data1.archived === undefined){ -const err4 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "archived"},message:"must have required property '"+"archived"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data1.title === undefined){ -const err5 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data1.cwd === undefined){ -const err6 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data1.running_agents === undefined){ -const err7 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "running_agents"},message:"must have required property '"+"running_agents"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data1.queued_agents === undefined){ -const err8 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "queued_agents"},message:"must have required property '"+"queued_agents"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data1.pending_permissions === undefined){ -const err9 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_permissions"},message:"must have required property '"+"pending_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data1.pending_questions === undefined){ -const err10 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "pending_questions"},message:"must have required property '"+"pending_questions"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data1.truncated === undefined){ -const err11 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/required",keyword:"required",params:{missingProperty: "truncated"},message:"must have required property '"+"truncated"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data1.root_id !== undefined){ -if(typeof data1.root_id !== "string"){ -const err12 = {instancePath:instancePath+"/items/" + i0+"/root_id",schemaPath:"#/properties/items/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data1.missing !== undefined){ -if(typeof data1.missing !== "boolean"){ -const err13 = {instancePath:instancePath+"/items/" + i0+"/missing",schemaPath:"#/properties/items/items/properties/missing/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data1.archived !== undefined){ -if(typeof data1.archived !== "boolean"){ -const err14 = {instancePath:instancePath+"/items/" + i0+"/archived",schemaPath:"#/properties/items/items/properties/archived/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data1.title !== undefined){ -if(typeof data1.title !== "string"){ -const err15 = {instancePath:instancePath+"/items/" + i0+"/title",schemaPath:"#/properties/items/items/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data1.cwd !== undefined){ -if(typeof data1.cwd !== "string"){ -const err16 = {instancePath:instancePath+"/items/" + i0+"/cwd",schemaPath:"#/properties/items/items/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data1.workspace_id !== undefined){ -if(typeof data1.workspace_id !== "string"){ -const err17 = {instancePath:instancePath+"/items/" + i0+"/workspace_id",schemaPath:"#/properties/items/items/properties/workspace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data1.running_agents !== undefined){ -let data8 = data1.running_agents; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err18 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err19 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -else { -const err20 = {instancePath:instancePath+"/items/" + i0+"/running_agents",schemaPath:"#/properties/items/items/properties/running_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data1.queued_agents !== undefined){ -let data9 = data1.queued_agents; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err21 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err22 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -else { -const err23 = {instancePath:instancePath+"/items/" + i0+"/queued_agents",schemaPath:"#/properties/items/items/properties/queued_agents/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data1.pending_permissions !== undefined){ -let data10 = data1.pending_permissions; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err24 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err25 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -else { -const err26 = {instancePath:instancePath+"/items/" + i0+"/pending_permissions",schemaPath:"#/properties/items/items/properties/pending_permissions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -if(data1.pending_questions !== undefined){ -let data11 = data1.pending_questions; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err27 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err28 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -else { -const err29 = {instancePath:instancePath+"/items/" + i0+"/pending_questions",schemaPath:"#/properties/items/items/properties/pending_questions/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -} -if(data1.truncated !== undefined){ -if(typeof data1.truncated !== "boolean"){ -const err30 = {instancePath:instancePath+"/items/" + i0+"/truncated",schemaPath:"#/properties/items/items/properties/truncated/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -} -else { -const err31 = {instancePath:instancePath+"/items/" + i0,schemaPath:"#/properties/items/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -} -else { -const err32 = {instancePath:instancePath+"/items",schemaPath:"#/properties/items/type",keyword:"type",params:{type: "array"},message:"must be array"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -} -} -else { -const err33 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -validate172.errors = vErrors; -return errors === 0; -} - -export const SessionTitleChangedParams = validate173; -const schema174 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SessionTitleChangedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionTitleChangedParams","required":["root_id"],"additionalProperties":true}; - -function validate173(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionTitleChangedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate173.errors = vErrors; -return errors === 0; -} - -export const SessionUpdateEvent = validate174; -const schema175 = {"type":"object","properties":{"archived":{"type":["null","boolean"]},"title":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"effort":{"type":"string"},"effort_changed":{"type":"boolean"},"working_directory":{"type":"string"},"permission_mode":{"type":["null","string"]}},"$id":"https://whip.dev/protocol/v6/SessionUpdateEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"SessionUpdateEvent","additionalProperties":true}; - -function validate174(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SessionUpdateEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.archived !== undefined){ -let data0 = data.archived; -if((data0 !== null) && (typeof data0 !== "boolean")){ -const err0 = {instancePath:instancePath+"/archived",schemaPath:"#/properties/archived/type",keyword:"type",params:{type: schema175.properties.archived.type},message:"must be null,boolean"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err1 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.model !== undefined){ -if(typeof data.model !== "string"){ -const err2 = {instancePath:instancePath+"/model",schemaPath:"#/properties/model/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.provider !== undefined){ -if(typeof data.provider !== "string"){ -const err3 = {instancePath:instancePath+"/provider",schemaPath:"#/properties/provider/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.effort !== undefined){ -if(typeof data.effort !== "string"){ -const err4 = {instancePath:instancePath+"/effort",schemaPath:"#/properties/effort/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.effort_changed !== undefined){ -if(typeof data.effort_changed !== "boolean"){ -const err5 = {instancePath:instancePath+"/effort_changed",schemaPath:"#/properties/effort_changed/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.working_directory !== undefined){ -if(typeof data.working_directory !== "string"){ -const err6 = {instancePath:instancePath+"/working_directory",schemaPath:"#/properties/working_directory/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.permission_mode !== undefined){ -let data7 = data.permission_mode; -if((data7 !== null) && (typeof data7 !== "string")){ -const err7 = {instancePath:instancePath+"/permission_mode",schemaPath:"#/properties/permission_mode/type",keyword:"type",params:{type: schema175.properties.permission_mode.type},message:"must be null,string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate174.errors = vErrors; -return errors === 0; -} - -export const ShellParams = validate175; -const schema176 = {"type":"object","properties":{"command":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ShellParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ShellParams","required":["command"],"additionalProperties":true}; - -function validate175(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ShellParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.command === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "command"},message:"must have required property '"+"command"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.command !== undefined){ -if(typeof data.command !== "string"){ -const err1 = {instancePath:instancePath+"/command",schemaPath:"#/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate175.errors = vErrors; -return errors === 0; -} - -export const SnapshotParams = validate176; -const schema177 = {"type":"object","properties":{"root_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/SnapshotParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SnapshotParams","required":["root_id"],"additionalProperties":true}; - -function validate176(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SnapshotParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate176.errors = vErrors; -return errors === 0; -} - -export const SpanPage = validate177; -const schema178 = {"type":"object","properties":{"root_id":{"type":"string"},"spans":{"type":["null","array"],"items":{"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}},"next_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"has_more":{"type":"boolean"},"server_time_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanPage","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanPage","required":["root_id","spans","next_seq","has_more","server_time_ns"],"additionalProperties":true}; - -function validate177(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SpanPage" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.spans === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "spans"},message:"must have required property '"+"spans"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.next_seq === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "next_seq"},message:"must have required property '"+"next_seq"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.has_more === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "has_more"},message:"must have required property '"+"has_more"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.server_time_ns === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "server_time_ns"},message:"must have required property '"+"server_time_ns"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.spans !== undefined){ -let data1 = data.spans; -if((data1 !== null) && (!(Array.isArray(data1)))){ -const err6 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: schema178.properties.spans.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(Array.isArray(data1)){ -const len0 = data1.length; -for(let i0=0; i0<len0; i0++){ -let data2 = data1[i0]; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.id === undefined){ -const err7 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.trace_id === undefined){ -const err8 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "trace_id"},message:"must have required property '"+"trace_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data2.root_id === undefined){ -const err9 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data2.agent_id === undefined){ -const err10 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data2.kind === undefined){ -const err11 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data2.name === undefined){ -const err12 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data2.status === undefined){ -const err13 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data2.start_ns === undefined){ -const err14 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "start_ns"},message:"must have required property '"+"start_ns"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data2.end_ns === undefined){ -const err15 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "end_ns"},message:"must have required property '"+"end_ns"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data2.updated_seq === undefined){ -const err16 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/required",keyword:"required",params:{missingProperty: "updated_seq"},message:"must have required property '"+"updated_seq"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data2.id !== undefined){ -if(typeof data2.id !== "string"){ -const err17 = {instancePath:instancePath+"/spans/" + i0+"/id",schemaPath:"#/properties/spans/items/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data2.trace_id !== undefined){ -if(typeof data2.trace_id !== "string"){ -const err18 = {instancePath:instancePath+"/spans/" + i0+"/trace_id",schemaPath:"#/properties/spans/items/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data2.parent_id !== undefined){ -if(typeof data2.parent_id !== "string"){ -const err19 = {instancePath:instancePath+"/spans/" + i0+"/parent_id",schemaPath:"#/properties/spans/items/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data2.root_id !== undefined){ -if(typeof data2.root_id !== "string"){ -const err20 = {instancePath:instancePath+"/spans/" + i0+"/root_id",schemaPath:"#/properties/spans/items/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data2.agent_id !== undefined){ -if(typeof data2.agent_id !== "string"){ -const err21 = {instancePath:instancePath+"/spans/" + i0+"/agent_id",schemaPath:"#/properties/spans/items/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data2.turn_id !== undefined){ -if(typeof data2.turn_id !== "string"){ -const err22 = {instancePath:instancePath+"/spans/" + i0+"/turn_id",schemaPath:"#/properties/spans/items/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data2.kind !== undefined){ -if(typeof data2.kind !== "string"){ -const err23 = {instancePath:instancePath+"/spans/" + i0+"/kind",schemaPath:"#/properties/spans/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err24 = {instancePath:instancePath+"/spans/" + i0+"/name",schemaPath:"#/properties/spans/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data2.status !== undefined){ -if(typeof data2.status !== "string"){ -const err25 = {instancePath:instancePath+"/spans/" + i0+"/status",schemaPath:"#/properties/spans/items/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data2.start_ns !== undefined){ -let data12 = data2.start_ns; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err26 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err27 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/spans/" + i0+"/start_ns",schemaPath:"#/properties/spans/items/properties/start_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data2.end_ns !== undefined){ -let data13 = data2.end_ns; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err29 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err30 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/spans/" + i0+"/end_ns",schemaPath:"#/properties/spans/items/properties/end_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data2.updated_seq !== undefined){ -let data14 = data2.updated_seq; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err32 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err33 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -else { -const err34 = {instancePath:instancePath+"/spans/" + i0+"/updated_seq",schemaPath:"#/properties/spans/items/properties/updated_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -} -else { -const err35 = {instancePath:instancePath+"/spans/" + i0,schemaPath:"#/properties/spans/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -} -} -if(data.next_seq !== undefined){ -let data15 = data.next_seq; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err36 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err37 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -else { -const err38 = {instancePath:instancePath+"/next_seq",schemaPath:"#/properties/next_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data.has_more !== undefined){ -if(typeof data.has_more !== "boolean"){ -const err39 = {instancePath:instancePath+"/has_more",schemaPath:"#/properties/has_more/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data.server_time_ns !== undefined){ -let data17 = data.server_time_ns; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err40 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err41 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -else { -const err42 = {instancePath:instancePath+"/server_time_ns",schemaPath:"#/properties/server_time_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -else { -const err43 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -validate177.errors = vErrors; -return errors === 0; -} - -export const SpanRecord = validate178; -const schema179 = {"type":"object","properties":{"id":{"type":"string"},"trace_id":{"type":"string"},"parent_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"start_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"end_ns":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"attrs":true,"links":true,"updated_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SpanRecord","$schema":"http://json-schema.org/draft-07/schema#","title":"SpanRecord","required":["id","trace_id","root_id","agent_id","kind","name","status","start_ns","end_ns","updated_seq"],"additionalProperties":true}; - -function validate178(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SpanRecord" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.trace_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "trace_id"},message:"must have required property '"+"trace_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.root_id === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.agent_id === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.kind === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.name === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.status === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "status"},message:"must have required property '"+"status"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.start_ns === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "start_ns"},message:"must have required property '"+"start_ns"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.end_ns === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "end_ns"},message:"must have required property '"+"end_ns"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.updated_seq === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "updated_seq"},message:"must have required property '"+"updated_seq"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err10 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err11 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.parent_id !== undefined){ -if(typeof data.parent_id !== "string"){ -const err12 = {instancePath:instancePath+"/parent_id",schemaPath:"#/properties/parent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err13 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err14 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err15 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.kind !== undefined){ -if(typeof data.kind !== "string"){ -const err16 = {instancePath:instancePath+"/kind",schemaPath:"#/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err17 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.status !== undefined){ -if(typeof data.status !== "string"){ -const err18 = {instancePath:instancePath+"/status",schemaPath:"#/properties/status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.start_ns !== undefined){ -let data9 = data.start_ns; -if(typeof data9 === "string"){ -if(!pattern0.test(data9)){ -const err19 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(!(formats0.validate(data9))){ -const err20 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -else { -const err21 = {instancePath:instancePath+"/start_ns",schemaPath:"#/properties/start_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data.end_ns !== undefined){ -let data10 = data.end_ns; -if(typeof data10 === "string"){ -if(!pattern0.test(data10)){ -const err22 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -if(!(formats0.validate(data10))){ -const err23 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -else { -const err24 = {instancePath:instancePath+"/end_ns",schemaPath:"#/properties/end_ns/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -if(data.updated_seq !== undefined){ -let data11 = data.updated_seq; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err25 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err26 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -} -else { -const err27 = {instancePath:instancePath+"/updated_seq",schemaPath:"#/properties/updated_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -} -else { -const err28 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -validate178.errors = vErrors; -return errors === 0; -} - -export const StreamEvent = validate179; -const schema180 = {"type":"object","properties":{"part_id":{"type":"string"},"display":{"type":["null","object"],"properties":{"target":{"type":"string"},"command":{"type":"string"},"query":{"type":"string"},"child_id":{"type":"string"},"label":{"type":"string"}},"additionalProperties":true},"accounting":{"type":["null","object"],"properties":{"root_id":{"type":"string"},"agent_id":{"type":"string"},"scope":{"type":"string"},"revision":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_micros":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"unknown_cost_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reported_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"estimated_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"pending_calls":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"required":["root_id","agent_id","scope","revision","reported_cost_micros","estimated_cost_micros","reported_cost_calls","estimated_cost_calls","unknown_cost_calls","reported_calls","estimated_calls","pending_calls"],"additionalProperties":true},"usage":{"type":["null","object"],"properties":{"used":{"type":"integer"},"size":{"type":"integer"},"usage":{"type":"object","properties":{"reported":{"type":"boolean"},"cost":{"type":["null","number"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"prompt_tokens_details":{"type":["null","object"],"properties":{"cached_tokens":{"type":"integer"}},"required":["cached_tokens"],"additionalProperties":true},"completion_tokens_details":{"type":["null","object"],"properties":{"reasoning_tokens":{"type":"integer"}},"required":["reasoning_tokens"],"additionalProperties":true}},"required":["prompt_tokens","completion_tokens"],"additionalProperties":true}},"required":["used","size","usage"],"additionalProperties":true},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"invocation_id":{"type":"string"},"operation_id":{"type":"string"},"host_status":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"text":{"type":"string"},"args":{"type":"string"},"result":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/StreamEvent","$schema":"http://json-schema.org/draft-07/schema#","title":"StreamEvent","additionalProperties":true}; - -function validate179(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/StreamEvent" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.part_id !== undefined){ -if(typeof data.part_id !== "string"){ -const err0 = {instancePath:instancePath+"/part_id",schemaPath:"#/properties/part_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -} -if(data.display !== undefined){ -let data1 = data.display; -if((data1 !== null) && (!(data1 && typeof data1 == "object" && !Array.isArray(data1)))){ -const err1 = {instancePath:instancePath+"/display",schemaPath:"#/properties/display/type",keyword:"type",params:{type: schema180.properties.display.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data1 && typeof data1 == "object" && !Array.isArray(data1)){ -if(data1.target !== undefined){ -if(typeof data1.target !== "string"){ -const err2 = {instancePath:instancePath+"/display/target",schemaPath:"#/properties/display/properties/target/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data1.command !== undefined){ -if(typeof data1.command !== "string"){ -const err3 = {instancePath:instancePath+"/display/command",schemaPath:"#/properties/display/properties/command/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data1.query !== undefined){ -if(typeof data1.query !== "string"){ -const err4 = {instancePath:instancePath+"/display/query",schemaPath:"#/properties/display/properties/query/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data1.child_id !== undefined){ -if(typeof data1.child_id !== "string"){ -const err5 = {instancePath:instancePath+"/display/child_id",schemaPath:"#/properties/display/properties/child_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data1.label !== undefined){ -if(typeof data1.label !== "string"){ -const err6 = {instancePath:instancePath+"/display/label",schemaPath:"#/properties/display/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -} -if(data.accounting !== undefined){ -let data7 = data.accounting; -if((data7 !== null) && (!(data7 && typeof data7 == "object" && !Array.isArray(data7)))){ -const err7 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/type",keyword:"type",params:{type: schema180.properties.accounting.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data7 && typeof data7 == "object" && !Array.isArray(data7)){ -if(data7.root_id === undefined){ -const err8 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data7.agent_id === undefined){ -const err9 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data7.scope === undefined){ -const err10 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "scope"},message:"must have required property '"+"scope"+"'"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -if(data7.revision === undefined){ -const err11 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -if(data7.reported_cost_micros === undefined){ -const err12 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_micros"},message:"must have required property '"+"reported_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -if(data7.estimated_cost_micros === undefined){ -const err13 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_micros"},message:"must have required property '"+"estimated_cost_micros"+"'"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(data7.reported_cost_calls === undefined){ -const err14 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_cost_calls"},message:"must have required property '"+"reported_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -if(data7.estimated_cost_calls === undefined){ -const err15 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_cost_calls"},message:"must have required property '"+"estimated_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -if(data7.unknown_cost_calls === undefined){ -const err16 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "unknown_cost_calls"},message:"must have required property '"+"unknown_cost_calls"+"'"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(data7.reported_calls === undefined){ -const err17 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "reported_calls"},message:"must have required property '"+"reported_calls"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data7.estimated_calls === undefined){ -const err18 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "estimated_calls"},message:"must have required property '"+"estimated_calls"+"'"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -if(data7.pending_calls === undefined){ -const err19 = {instancePath:instancePath+"/accounting",schemaPath:"#/properties/accounting/required",keyword:"required",params:{missingProperty: "pending_calls"},message:"must have required property '"+"pending_calls"+"'"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -if(data7.root_id !== undefined){ -if(typeof data7.root_id !== "string"){ -const err20 = {instancePath:instancePath+"/accounting/root_id",schemaPath:"#/properties/accounting/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -} -if(data7.agent_id !== undefined){ -if(typeof data7.agent_id !== "string"){ -const err21 = {instancePath:instancePath+"/accounting/agent_id",schemaPath:"#/properties/accounting/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -if(data7.scope !== undefined){ -if(typeof data7.scope !== "string"){ -const err22 = {instancePath:instancePath+"/accounting/scope",schemaPath:"#/properties/accounting/properties/scope/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -if(data7.revision !== undefined){ -let data11 = data7.revision; -if(typeof data11 === "string"){ -if(!pattern0.test(data11)){ -const err23 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -if(!(formats0.validate(data11))){ -const err24 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -else { -const err25 = {instancePath:instancePath+"/accounting/revision",schemaPath:"#/properties/accounting/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -if(data7.reported_cost_micros !== undefined){ -let data12 = data7.reported_cost_micros; -if(typeof data12 === "string"){ -if(!pattern0.test(data12)){ -const err26 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(!(formats0.validate(data12))){ -const err27 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -} -else { -const err28 = {instancePath:instancePath+"/accounting/reported_cost_micros",schemaPath:"#/properties/accounting/properties/reported_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -} -if(data7.estimated_cost_micros !== undefined){ -let data13 = data7.estimated_cost_micros; -if(typeof data13 === "string"){ -if(!pattern0.test(data13)){ -const err29 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!(formats0.validate(data13))){ -const err30 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -else { -const err31 = {instancePath:instancePath+"/accounting/estimated_cost_micros",schemaPath:"#/properties/accounting/properties/estimated_cost_micros/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -} -if(data7.reported_cost_calls !== undefined){ -let data14 = data7.reported_cost_calls; -if(typeof data14 === "string"){ -if(!pattern0.test(data14)){ -const err32 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(!(formats0.validate(data14))){ -const err33 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -} -else { -const err34 = {instancePath:instancePath+"/accounting/reported_cost_calls",schemaPath:"#/properties/accounting/properties/reported_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data7.estimated_cost_calls !== undefined){ -let data15 = data7.estimated_cost_calls; -if(typeof data15 === "string"){ -if(!pattern0.test(data15)){ -const err35 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -if(!(formats0.validate(data15))){ -const err36 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -} -else { -const err37 = {instancePath:instancePath+"/accounting/estimated_cost_calls",schemaPath:"#/properties/accounting/properties/estimated_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -if(data7.unknown_cost_calls !== undefined){ -let data16 = data7.unknown_cost_calls; -if(typeof data16 === "string"){ -if(!pattern0.test(data16)){ -const err38 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -if(!(formats0.validate(data16))){ -const err39 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -else { -const err40 = {instancePath:instancePath+"/accounting/unknown_cost_calls",schemaPath:"#/properties/accounting/properties/unknown_cost_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -if(data7.reported_calls !== undefined){ -let data17 = data7.reported_calls; -if(typeof data17 === "string"){ -if(!pattern0.test(data17)){ -const err41 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -if(!(formats0.validate(data17))){ -const err42 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -else { -const err43 = {instancePath:instancePath+"/accounting/reported_calls",schemaPath:"#/properties/accounting/properties/reported_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -if(data7.estimated_calls !== undefined){ -let data18 = data7.estimated_calls; -if(typeof data18 === "string"){ -if(!pattern0.test(data18)){ -const err44 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -if(!(formats0.validate(data18))){ -const err45 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err45]; -} -else { -vErrors.push(err45); -} -errors++; -} -} -else { -const err46 = {instancePath:instancePath+"/accounting/estimated_calls",schemaPath:"#/properties/accounting/properties/estimated_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err46]; -} -else { -vErrors.push(err46); -} -errors++; -} -} -if(data7.pending_calls !== undefined){ -let data19 = data7.pending_calls; -if(typeof data19 === "string"){ -if(!pattern0.test(data19)){ -const err47 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err47]; -} -else { -vErrors.push(err47); -} -errors++; -} -if(!(formats0.validate(data19))){ -const err48 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err48]; -} -else { -vErrors.push(err48); -} -errors++; -} -} -else { -const err49 = {instancePath:instancePath+"/accounting/pending_calls",schemaPath:"#/properties/accounting/properties/pending_calls/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err49]; -} -else { -vErrors.push(err49); -} -errors++; -} -} -} -} -if(data.usage !== undefined){ -let data20 = data.usage; -if((data20 !== null) && (!(data20 && typeof data20 == "object" && !Array.isArray(data20)))){ -const err50 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/type",keyword:"type",params:{type: schema180.properties.usage.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err50]; -} -else { -vErrors.push(err50); -} -errors++; -} -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.used === undefined){ -const err51 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "used"},message:"must have required property '"+"used"+"'"}; -if(vErrors === null){ -vErrors = [err51]; -} -else { -vErrors.push(err51); -} -errors++; -} -if(data20.size === undefined){ -const err52 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err52]; -} -else { -vErrors.push(err52); -} -errors++; -} -if(data20.usage === undefined){ -const err53 = {instancePath:instancePath+"/usage",schemaPath:"#/properties/usage/required",keyword:"required",params:{missingProperty: "usage"},message:"must have required property '"+"usage"+"'"}; -if(vErrors === null){ -vErrors = [err53]; -} -else { -vErrors.push(err53); -} -errors++; -} -if(data20.used !== undefined){ -let data21 = data20.used; -if(!((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21)))){ -const err54 = {instancePath:instancePath+"/usage/used",schemaPath:"#/properties/usage/properties/used/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err54]; -} -else { -vErrors.push(err54); -} -errors++; -} -} -if(data20.size !== undefined){ -let data22 = data20.size; -if(!((typeof data22 == "number") && (!(data22 % 1) && !isNaN(data22)))){ -const err55 = {instancePath:instancePath+"/usage/size",schemaPath:"#/properties/usage/properties/size/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err55]; -} -else { -vErrors.push(err55); -} -errors++; -} -} -if(data20.usage !== undefined){ -let data23 = data20.usage; -if(data23 && typeof data23 == "object" && !Array.isArray(data23)){ -if(data23.prompt_tokens === undefined){ -const err56 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "prompt_tokens"},message:"must have required property '"+"prompt_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err56]; -} -else { -vErrors.push(err56); -} -errors++; -} -if(data23.completion_tokens === undefined){ -const err57 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/required",keyword:"required",params:{missingProperty: "completion_tokens"},message:"must have required property '"+"completion_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err57]; -} -else { -vErrors.push(err57); -} -errors++; -} -if(data23.reported !== undefined){ -if(typeof data23.reported !== "boolean"){ -const err58 = {instancePath:instancePath+"/usage/usage/reported",schemaPath:"#/properties/usage/properties/usage/properties/reported/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err58]; -} -else { -vErrors.push(err58); -} -errors++; -} -} -if(data23.cost !== undefined){ -let data25 = data23.cost; -if((data25 !== null) && (!(typeof data25 == "number"))){ -const err59 = {instancePath:instancePath+"/usage/usage/cost",schemaPath:"#/properties/usage/properties/usage/properties/cost/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.cost.type},message:"must be null,number"}; -if(vErrors === null){ -vErrors = [err59]; -} -else { -vErrors.push(err59); -} -errors++; -} -} -if(data23.prompt_tokens !== undefined){ -let data26 = data23.prompt_tokens; -if(!((typeof data26 == "number") && (!(data26 % 1) && !isNaN(data26)))){ -const err60 = {instancePath:instancePath+"/usage/usage/prompt_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err60]; -} -else { -vErrors.push(err60); -} -errors++; -} -} -if(data23.completion_tokens !== undefined){ -let data27 = data23.completion_tokens; -if(!((typeof data27 == "number") && (!(data27 % 1) && !isNaN(data27)))){ -const err61 = {instancePath:instancePath+"/usage/usage/completion_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err61]; -} -else { -vErrors.push(err61); -} -errors++; -} -} -if(data23.prompt_tokens_details !== undefined){ -let data28 = data23.prompt_tokens_details; -if((data28 !== null) && (!(data28 && typeof data28 == "object" && !Array.isArray(data28)))){ -const err62 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.prompt_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err62]; -} -else { -vErrors.push(err62); -} -errors++; -} -if(data28 && typeof data28 == "object" && !Array.isArray(data28)){ -if(data28.cached_tokens === undefined){ -const err63 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/required",keyword:"required",params:{missingProperty: "cached_tokens"},message:"must have required property '"+"cached_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err63]; -} -else { -vErrors.push(err63); -} -errors++; -} -if(data28.cached_tokens !== undefined){ -let data29 = data28.cached_tokens; -if(!((typeof data29 == "number") && (!(data29 % 1) && !isNaN(data29)))){ -const err64 = {instancePath:instancePath+"/usage/usage/prompt_tokens_details/cached_tokens",schemaPath:"#/properties/usage/properties/usage/properties/prompt_tokens_details/properties/cached_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err64]; -} -else { -vErrors.push(err64); -} -errors++; -} -} -} -} -if(data23.completion_tokens_details !== undefined){ -let data30 = data23.completion_tokens_details; -if((data30 !== null) && (!(data30 && typeof data30 == "object" && !Array.isArray(data30)))){ -const err65 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/type",keyword:"type",params:{type: schema180.properties.usage.properties.usage.properties.completion_tokens_details.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err65]; -} -else { -vErrors.push(err65); -} -errors++; -} -if(data30 && typeof data30 == "object" && !Array.isArray(data30)){ -if(data30.reasoning_tokens === undefined){ -const err66 = {instancePath:instancePath+"/usage/usage/completion_tokens_details",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/required",keyword:"required",params:{missingProperty: "reasoning_tokens"},message:"must have required property '"+"reasoning_tokens"+"'"}; -if(vErrors === null){ -vErrors = [err66]; -} -else { -vErrors.push(err66); -} -errors++; -} -if(data30.reasoning_tokens !== undefined){ -let data31 = data30.reasoning_tokens; -if(!((typeof data31 == "number") && (!(data31 % 1) && !isNaN(data31)))){ -const err67 = {instancePath:instancePath+"/usage/usage/completion_tokens_details/reasoning_tokens",schemaPath:"#/properties/usage/properties/usage/properties/completion_tokens_details/properties/reasoning_tokens/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err67]; -} -else { -vErrors.push(err67); -} -errors++; -} -} -} -} -} -else { -const err68 = {instancePath:instancePath+"/usage/usage",schemaPath:"#/properties/usage/properties/usage/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err68]; -} -else { -vErrors.push(err68); -} -errors++; -} -} -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err69 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err69]; -} -else { -vErrors.push(err69); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err70 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err70]; -} -else { -vErrors.push(err70); -} -errors++; -} -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err71 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err71]; -} -else { -vErrors.push(err71); -} -errors++; -} -} -if(data.operation_id !== undefined){ -if(typeof data.operation_id !== "string"){ -const err72 = {instancePath:instancePath+"/operation_id",schemaPath:"#/properties/operation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err72]; -} -else { -vErrors.push(err72); -} -errors++; -} -} -if(data.host_status !== undefined){ -if(typeof data.host_status !== "string"){ -const err73 = {instancePath:instancePath+"/host_status",schemaPath:"#/properties/host_status/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err73]; -} -else { -vErrors.push(err73); -} -errors++; -} -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err74 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err74]; -} -else { -vErrors.push(err74); -} -errors++; -} -} -if(data.name !== undefined){ -if(typeof data.name !== "string"){ -const err75 = {instancePath:instancePath+"/name",schemaPath:"#/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err75]; -} -else { -vErrors.push(err75); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err76 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err76]; -} -else { -vErrors.push(err76); -} -errors++; -} -} -if(data.args !== undefined){ -if(typeof data.args !== "string"){ -const err77 = {instancePath:instancePath+"/args",schemaPath:"#/properties/args/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err77]; -} -else { -vErrors.push(err77); -} -errors++; -} -} -if(data.result !== undefined){ -if(typeof data.result !== "string"){ -const err78 = {instancePath:instancePath+"/result",schemaPath:"#/properties/result/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err78]; -} -else { -vErrors.push(err78); -} -errors++; -} -} -} -else { -const err79 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err79]; -} -else { -vErrors.push(err79); -} -errors++; -} -validate179.errors = vErrors; -return errors === 0; -} - -export const SubmitPayload = validate180; -const schema181 = {"type":"object","properties":{"design_context":{"type":["null","object"],"properties":{"context_attachment_id":{"type":"string"},"screenshot_attachment_id":{"type":"string"},"elements":{"type":["null","array"],"items":{"type":"object","properties":{"label":{"type":"string"},"selector":{"type":"string"}},"required":["label"],"additionalProperties":true}},"element_count":{"type":"integer"},"page_url":{"type":"string"},"page_title":{"type":"string"}},"required":["context_attachment_id","elements","element_count"],"additionalProperties":true},"text":{"type":"string"},"parts":{"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"},"image_url":{"type":["null","object"],"properties":{"url":{"type":"string"}},"required":["url"],"additionalProperties":true},"w":{"type":"integer"},"h":{"type":"integer"}},"required":["type"],"additionalProperties":true}},"attachments":{"type":["null","array"],"items":{"type":"object","properties":{"kind":{"type":"string","enum":["image","text"]},"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"name":{"type":"string"}},"required":["kind","content"],"additionalProperties":true}}},"$id":"https://whip.dev/protocol/v6/SubmitPayload","$schema":"http://json-schema.org/draft-07/schema#","title":"SubmitPayload","required":["text"],"additionalProperties":true}; - -function validate180(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubmitPayload" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.design_context !== undefined){ -let data0 = data.design_context; -if((data0 !== null) && (!(data0 && typeof data0 == "object" && !Array.isArray(data0)))){ -const err1 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/type",keyword:"type",params:{type: schema181.properties.design_context.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.context_attachment_id === undefined){ -const err2 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "context_attachment_id"},message:"must have required property '"+"context_attachment_id"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.elements === undefined){ -const err3 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "elements"},message:"must have required property '"+"elements"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.element_count === undefined){ -const err4 = {instancePath:instancePath+"/design_context",schemaPath:"#/properties/design_context/required",keyword:"required",params:{missingProperty: "element_count"},message:"must have required property '"+"element_count"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.context_attachment_id !== undefined){ -if(typeof data0.context_attachment_id !== "string"){ -const err5 = {instancePath:instancePath+"/design_context/context_attachment_id",schemaPath:"#/properties/design_context/properties/context_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data0.screenshot_attachment_id !== undefined){ -if(typeof data0.screenshot_attachment_id !== "string"){ -const err6 = {instancePath:instancePath+"/design_context/screenshot_attachment_id",schemaPath:"#/properties/design_context/properties/screenshot_attachment_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.elements !== undefined){ -let data3 = data0.elements; -if((data3 !== null) && (!(Array.isArray(data3)))){ -const err7 = {instancePath:instancePath+"/design_context/elements",schemaPath:"#/properties/design_context/properties/elements/type",keyword:"type",params:{type: schema181.properties.design_context.properties.elements.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(Array.isArray(data3)){ -const len0 = data3.length; -for(let i0=0; i0<len0; i0++){ -let data4 = data3[i0]; -if(data4 && typeof data4 == "object" && !Array.isArray(data4)){ -if(data4.label === undefined){ -const err8 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/required",keyword:"required",params:{missingProperty: "label"},message:"must have required property '"+"label"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data4.label !== undefined){ -if(typeof data4.label !== "string"){ -const err9 = {instancePath:instancePath+"/design_context/elements/" + i0+"/label",schemaPath:"#/properties/design_context/properties/elements/items/properties/label/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data4.selector !== undefined){ -if(typeof data4.selector !== "string"){ -const err10 = {instancePath:instancePath+"/design_context/elements/" + i0+"/selector",schemaPath:"#/properties/design_context/properties/elements/items/properties/selector/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -else { -const err11 = {instancePath:instancePath+"/design_context/elements/" + i0,schemaPath:"#/properties/design_context/properties/elements/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -} -} -if(data0.element_count !== undefined){ -let data7 = data0.element_count; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err12 = {instancePath:instancePath+"/design_context/element_count",schemaPath:"#/properties/design_context/properties/element_count/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data0.page_url !== undefined){ -if(typeof data0.page_url !== "string"){ -const err13 = {instancePath:instancePath+"/design_context/page_url",schemaPath:"#/properties/design_context/properties/page_url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data0.page_title !== undefined){ -if(typeof data0.page_title !== "string"){ -const err14 = {instancePath:instancePath+"/design_context/page_title",schemaPath:"#/properties/design_context/properties/page_title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err15 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.parts !== undefined){ -let data11 = data.parts; -if((data11 !== null) && (!(Array.isArray(data11)))){ -const err16 = {instancePath:instancePath+"/parts",schemaPath:"#/properties/parts/type",keyword:"type",params:{type: schema181.properties.parts.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -if(Array.isArray(data11)){ -const len1 = data11.length; -for(let i1=0; i1<len1; i1++){ -let data12 = data11[i1]; -if(data12 && typeof data12 == "object" && !Array.isArray(data12)){ -if(data12.type === undefined){ -const err17 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -if(data12.type !== undefined){ -if(typeof data12.type !== "string"){ -const err18 = {instancePath:instancePath+"/parts/" + i1+"/type",schemaPath:"#/properties/parts/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data12.text !== undefined){ -if(typeof data12.text !== "string"){ -const err19 = {instancePath:instancePath+"/parts/" + i1+"/text",schemaPath:"#/properties/parts/items/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data12.image_url !== undefined){ -let data15 = data12.image_url; -if((data15 !== null) && (!(data15 && typeof data15 == "object" && !Array.isArray(data15)))){ -const err20 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/type",keyword:"type",params:{type: schema181.properties.parts.items.properties.image_url.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(data15 && typeof data15 == "object" && !Array.isArray(data15)){ -if(data15.url === undefined){ -const err21 = {instancePath:instancePath+"/parts/" + i1+"/image_url",schemaPath:"#/properties/parts/items/properties/image_url/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -if(data15.url !== undefined){ -if(typeof data15.url !== "string"){ -const err22 = {instancePath:instancePath+"/parts/" + i1+"/image_url/url",schemaPath:"#/properties/parts/items/properties/image_url/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -} -if(data12.w !== undefined){ -let data17 = data12.w; -if(!((typeof data17 == "number") && (!(data17 % 1) && !isNaN(data17)))){ -const err23 = {instancePath:instancePath+"/parts/" + i1+"/w",schemaPath:"#/properties/parts/items/properties/w/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -} -if(data12.h !== undefined){ -let data18 = data12.h; -if(!((typeof data18 == "number") && (!(data18 % 1) && !isNaN(data18)))){ -const err24 = {instancePath:instancePath+"/parts/" + i1+"/h",schemaPath:"#/properties/parts/items/properties/h/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err24]; -} -else { -vErrors.push(err24); -} -errors++; -} -} -} -else { -const err25 = {instancePath:instancePath+"/parts/" + i1,schemaPath:"#/properties/parts/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err25]; -} -else { -vErrors.push(err25); -} -errors++; -} -} -} -} -if(data.attachments !== undefined){ -let data19 = data.attachments; -if((data19 !== null) && (!(Array.isArray(data19)))){ -const err26 = {instancePath:instancePath+"/attachments",schemaPath:"#/properties/attachments/type",keyword:"type",params:{type: schema181.properties.attachments.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err26]; -} -else { -vErrors.push(err26); -} -errors++; -} -if(Array.isArray(data19)){ -const len2 = data19.length; -for(let i2=0; i2<len2; i2++){ -let data20 = data19[i2]; -if(data20 && typeof data20 == "object" && !Array.isArray(data20)){ -if(data20.kind === undefined){ -const err27 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err27]; -} -else { -vErrors.push(err27); -} -errors++; -} -if(data20.content === undefined){ -const err28 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err28]; -} -else { -vErrors.push(err28); -} -errors++; -} -if(data20.kind !== undefined){ -let data21 = data20.kind; -if(typeof data21 !== "string"){ -const err29 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err29]; -} -else { -vErrors.push(err29); -} -errors++; -} -if(!((data21 === "image") || (data21 === "text"))){ -const err30 = {instancePath:instancePath+"/attachments/" + i2+"/kind",schemaPath:"#/properties/attachments/items/properties/kind/enum",keyword:"enum",params:{allowedValues: schema181.properties.attachments.items.properties.kind.enum},message:"must be equal to one of the allowed values"}; -if(vErrors === null){ -vErrors = [err30]; -} -else { -vErrors.push(err30); -} -errors++; -} -} -if(data20.content !== undefined){ -let data22 = data20.content; -if(data22 && typeof data22 == "object" && !Array.isArray(data22)){ -if(data22.reference_id === undefined){ -const err31 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err31]; -} -else { -vErrors.push(err31); -} -errors++; -} -if(data22.digest === undefined){ -const err32 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err32]; -} -else { -vErrors.push(err32); -} -errors++; -} -if(data22.size === undefined){ -const err33 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err33]; -} -else { -vErrors.push(err33); -} -errors++; -} -if(data22.reference_id !== undefined){ -if(typeof data22.reference_id !== "string"){ -const err34 = {instancePath:instancePath+"/attachments/" + i2+"/content/reference_id",schemaPath:"#/properties/attachments/items/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err34]; -} -else { -vErrors.push(err34); -} -errors++; -} -} -if(data22.digest !== undefined){ -if(typeof data22.digest !== "string"){ -const err35 = {instancePath:instancePath+"/attachments/" + i2+"/content/digest",schemaPath:"#/properties/attachments/items/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err35]; -} -else { -vErrors.push(err35); -} -errors++; -} -} -if(data22.size !== undefined){ -let data25 = data22.size; -if(typeof data25 === "string"){ -if(!pattern0.test(data25)){ -const err36 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err36]; -} -else { -vErrors.push(err36); -} -errors++; -} -if(!(formats0.validate(data25))){ -const err37 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err37]; -} -else { -vErrors.push(err37); -} -errors++; -} -} -else { -const err38 = {instancePath:instancePath+"/attachments/" + i2+"/content/size",schemaPath:"#/properties/attachments/items/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err38]; -} -else { -vErrors.push(err38); -} -errors++; -} -} -if(data22.media_type !== undefined){ -if(typeof data22.media_type !== "string"){ -const err39 = {instancePath:instancePath+"/attachments/" + i2+"/content/media_type",schemaPath:"#/properties/attachments/items/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err39]; -} -else { -vErrors.push(err39); -} -errors++; -} -} -if(data22.source !== undefined){ -if(typeof data22.source !== "string"){ -const err40 = {instancePath:instancePath+"/attachments/" + i2+"/content/source",schemaPath:"#/properties/attachments/items/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err40]; -} -else { -vErrors.push(err40); -} -errors++; -} -} -} -else { -const err41 = {instancePath:instancePath+"/attachments/" + i2+"/content",schemaPath:"#/properties/attachments/items/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err41]; -} -else { -vErrors.push(err41); -} -errors++; -} -} -if(data20.name !== undefined){ -if(typeof data20.name !== "string"){ -const err42 = {instancePath:instancePath+"/attachments/" + i2+"/name",schemaPath:"#/properties/attachments/items/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err42]; -} -else { -vErrors.push(err42); -} -errors++; -} -} -} -else { -const err43 = {instancePath:instancePath+"/attachments/" + i2,schemaPath:"#/properties/attachments/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err43]; -} -else { -vErrors.push(err43); -} -errors++; -} -} -} -} -} -else { -const err44 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err44]; -} -else { -vErrors.push(err44); -} -errors++; -} -validate180.errors = vErrors; -return errors === 0; -} - -export const SubscribeParams = validate181; -const schema182 = {"type":"object","properties":{"root_id":{"type":"string"},"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeParams","required":["root_id","subscription_id","cursor"],"additionalProperties":true}; - -function validate181(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscribeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.subscription_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cursor === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err4 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data2 = data.cursor; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate181.errors = vErrors; -return errors === 0; -} - -export const SubscribeResult = validate182; -const schema183 = {"type":"object","properties":{"subscription_id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/SubscribeResult","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscribeResult","required":["subscription_id","cursor"],"additionalProperties":true}; - -function validate182(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscribeResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err2 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate182.errors = vErrors; -return errors === 0; -} - -export const SubscriptionFailure = validate183; -const schema184 = {"type":"object","properties":{"subscription_id":{"type":"string"},"root_id":{"type":"string"},"error":{"type":["null","object"],"properties":{"data":{"type":["null","object"],"properties":{"kind":{"type":"string"}},"required":["kind"],"additionalProperties":true},"code":{"type":"integer"},"message":{"type":"string"}},"required":["code","message"],"additionalProperties":true}},"$id":"https://whip.dev/protocol/v6/SubscriptionFailure","$schema":"http://json-schema.org/draft-07/schema#","title":"SubscriptionFailure","required":["subscription_id","root_id","error"],"additionalProperties":true}; - -function validate183(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/SubscriptionFailure" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.error === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "error"},message:"must have required property '"+"error"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err3 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err4 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.error !== undefined){ -let data2 = data.error; -if((data2 !== null) && (!(data2 && typeof data2 == "object" && !Array.isArray(data2)))){ -const err5 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: schema184.properties.error.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.code === undefined){ -const err6 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "code"},message:"must have required property '"+"code"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2.message === undefined){ -const err7 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/required",keyword:"required",params:{missingProperty: "message"},message:"must have required property '"+"message"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data2.data !== undefined){ -let data3 = data2.data; -if((data3 !== null) && (!(data3 && typeof data3 == "object" && !Array.isArray(data3)))){ -const err8 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/type",keyword:"type",params:{type: schema184.properties.error.properties.data.type},message:"must be null,object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data3 && typeof data3 == "object" && !Array.isArray(data3)){ -if(data3.kind === undefined){ -const err9 = {instancePath:instancePath+"/error/data",schemaPath:"#/properties/error/properties/data/required",keyword:"required",params:{missingProperty: "kind"},message:"must have required property '"+"kind"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data3.kind !== undefined){ -if(typeof data3.kind !== "string"){ -const err10 = {instancePath:instancePath+"/error/data/kind",schemaPath:"#/properties/error/properties/data/properties/kind/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -} -if(data2.code !== undefined){ -let data5 = data2.code; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err11 = {instancePath:instancePath+"/error/code",schemaPath:"#/properties/error/properties/code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data2.message !== undefined){ -if(typeof data2.message !== "string"){ -const err12 = {instancePath:instancePath+"/error/message",schemaPath:"#/properties/error/properties/message/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate183.errors = vErrors; -return errors === 0; -} - -export const TerminalAttachParams = validate184; -const schema185 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachParams","required":["id","cursor"],"additionalProperties":true}; - -function validate184(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate184.errors = vErrors; -return errors === 0; -} - -export const TerminalAttachResult = validate185; -const schema186 = {"type":"object","properties":{"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"cwd":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"},"exited":{"type":"boolean"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalAttachResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalAttachResult","required":["cursor","cwd","cols","rows","exited"],"additionalProperties":true}; - -function validate185(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalAttachResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cursor === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cwd === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cols === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.rows === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.exited === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "exited"},message:"must have required property '"+"exited"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.cursor !== undefined){ -let data0 = data.cursor; -if(typeof data0 === "string"){ -if(!pattern0.test(data0)){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(!(formats0.validate(data0))){ -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -else { -const err7 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err8 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -if(data.cols !== undefined){ -let data2 = data.cols; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err9 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -if(data.rows !== undefined){ -let data3 = data.rows; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err10 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.exited !== undefined){ -if(typeof data.exited !== "boolean"){ -const err11 = {instancePath:instancePath+"/exited",schemaPath:"#/properties/exited/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.exit_code !== undefined){ -let data5 = data.exit_code; -if(!((typeof data5 == "number") && (!(data5 % 1) && !isNaN(data5)))){ -const err12 = {instancePath:instancePath+"/exit_code",schemaPath:"#/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.signal !== undefined){ -if(typeof data.signal !== "string"){ -const err13 = {instancePath:instancePath+"/signal",schemaPath:"#/properties/signal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -} -else { -const err14 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -validate185.errors = vErrors; -return errors === 0; -} - -export const TerminalDetachedParams = validate186; -const schema187 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalDetachedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalDetachedParams","required":["id"],"additionalProperties":true}; - -function validate186(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalDetachedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err1 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate186.errors = vErrors; -return errors === 0; -} - -export const TerminalExitedParams = validate187; -const schema188 = {"type":"object","properties":{"id":{"type":"string"},"exit_code":{"type":"integer"},"signal":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalExitedParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalExitedParams","required":["id","exit_code"],"additionalProperties":true}; - -function validate187(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalExitedParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.exit_code === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "exit_code"},message:"must have required property '"+"exit_code"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.exit_code !== undefined){ -let data1 = data.exit_code; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err3 = {instancePath:instancePath+"/exit_code",schemaPath:"#/properties/exit_code/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.signal !== undefined){ -if(typeof data.signal !== "string"){ -const err4 = {instancePath:instancePath+"/signal",schemaPath:"#/properties/signal/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate187.errors = vErrors; -return errors === 0; -} - -export const TerminalIDParams = validate188; -const schema189 = {"type":"object","properties":{"id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalIDParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalIDParams","required":["id"],"additionalProperties":true}; - -function validate188(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalIDParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err1 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate188.errors = vErrors; -return errors === 0; -} - -export const TerminalInputParams = validate189; -const schema190 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalInputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalInputParams","required":["id","bytes"],"additionalProperties":true}; - -function validate189(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalInputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data1 = data.bytes; -if((typeof data1 !== "string") && (data1 !== null)){ -const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema190.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern52.test(data1)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate189.errors = vErrors; -return errors === 0; -} - -export const TerminalOpenParams = validate190; -const schema191 = {"type":"object","properties":{"cwd":{"type":"string"},"root_id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenParams","required":["cols","rows"],"additionalProperties":true}; - -function validate190(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.cols === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.rows === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err2 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err3 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cols !== undefined){ -let data2 = data.cols; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err4 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.rows !== undefined){ -let data3 = data.rows; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err5 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate190.errors = vErrors; -return errors === 0; -} - -export const TerminalOpenResult = validate191; -const schema192 = {"type":"object","properties":{"id":{"type":"string"},"shell":{"type":"string"},"cwd":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TerminalOpenResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOpenResult","required":["id","shell","cwd"],"additionalProperties":true}; - -function validate191(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOpenResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.shell === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "shell"},message:"must have required property '"+"shell"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.cwd === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cwd"},message:"must have required property '"+"cwd"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.shell !== undefined){ -if(typeof data.shell !== "string"){ -const err4 = {instancePath:instancePath+"/shell",schemaPath:"#/properties/shell/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.cwd !== undefined){ -if(typeof data.cwd !== "string"){ -const err5 = {instancePath:instancePath+"/cwd",schemaPath:"#/properties/cwd/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate191.errors = vErrors; -return errors === 0; -} - -export const TerminalOutputParams = validate192; -const schema193 = {"type":"object","properties":{"id":{"type":"string"},"cursor":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalOutputParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalOutputParams","required":["id","cursor","bytes"],"additionalProperties":true}; - -function validate192(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalOutputParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cursor === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cursor"},message:"must have required property '"+"cursor"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.bytes === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cursor !== undefined){ -let data1 = data.cursor; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/cursor",schemaPath:"#/properties/cursor/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data2 = data.bytes; -if((typeof data2 !== "string") && (data2 !== null)){ -const err7 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema193.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(typeof data2 === "string"){ -if(!pattern52.test(data2)){ -const err8 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate192.errors = vErrors; -return errors === 0; -} - -export const TerminalResizeParams = validate193; -const schema194 = {"type":"object","properties":{"id":{"type":"string"},"cols":{"type":"integer"},"rows":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TerminalResizeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalResizeParams","required":["id","cols","rows"],"additionalProperties":true}; - -function validate193(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalResizeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.cols === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "cols"},message:"must have required property '"+"cols"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.rows === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "rows"},message:"must have required property '"+"rows"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err3 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.cols !== undefined){ -let data1 = data.cols; -if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){ -const err4 = {instancePath:instancePath+"/cols",schemaPath:"#/properties/cols/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.rows !== undefined){ -let data2 = data.rows; -if(!((typeof data2 == "number") && (!(data2 % 1) && !isNaN(data2)))){ -const err5 = {instancePath:instancePath+"/rows",schemaPath:"#/properties/rows/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -} -else { -const err6 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -validate193.errors = vErrors; -return errors === 0; -} - -export const TerminalWriteParams = validate194; -const schema195 = {"type":"object","properties":{"id":{"type":"string"},"bytes":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/TerminalWriteParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TerminalWriteParams","required":["id","bytes"],"additionalProperties":true}; - -function validate194(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TerminalWriteParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "id"},message:"must have required property '"+"id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.bytes === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "bytes"},message:"must have required property '"+"bytes"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.id !== undefined){ -if(typeof data.id !== "string"){ -const err2 = {instancePath:instancePath+"/id",schemaPath:"#/properties/id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.bytes !== undefined){ -let data1 = data.bytes; -if((typeof data1 !== "string") && (data1 !== null)){ -const err3 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/type",keyword:"type",params:{type: schema195.properties.bytes.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(typeof data1 === "string"){ -if(!pattern52.test(data1)){ -const err4 = {instancePath:instancePath+"/bytes",schemaPath:"#/properties/bytes/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -} -} -else { -const err5 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -validate194.errors = vErrors; -return errors === 0; -} - -export const TextParams = validate195; -const schema196 = {"type":"object","properties":{"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TextParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TextParams","required":["text"],"additionalProperties":true}; - -function validate195(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TextParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err1 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate195.errors = vErrors; -return errors === 0; -} - -export const TextResult = validate196; -const schema197 = {"type":"object","properties":{"text":{"type":"string"},"output":true},"$id":"https://whip.dev/protocol/v6/TextResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TextResult","required":["text"],"additionalProperties":true}; - -function validate196(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TextResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.text === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err1 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate196.errors = vErrors; -return errors === 0; -} - -export const TitleParams = validate197; -const schema198 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleParams","required":["title"],"additionalProperties":true}; - -function validate197(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TitleParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.title === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err1 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate197.errors = vErrors; -return errors === 0; -} - -export const TitleResult = validate198; -const schema199 = {"type":"object","properties":{"title":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TitleResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TitleResult","required":["title"],"additionalProperties":true}; - -function validate198(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TitleResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.title === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "title"},message:"must have required property '"+"title"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.title !== undefined){ -if(typeof data.title !== "string"){ -const err1 = {instancePath:instancePath+"/title",schemaPath:"#/properties/title/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate198.errors = vErrors; -return errors === 0; -} - -export const ToolCallParams = validate199; -const schema200 = {"type":"object","properties":{"tool":{"type":"string"},"arguments":true},"$id":"https://whip.dev/protocol/v6/ToolCallParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCallParams","required":["tool","arguments"],"additionalProperties":true}; - -function validate199(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolCallParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.tool === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.arguments === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "arguments"},message:"must have required property '"+"arguments"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.tool !== undefined){ -if(typeof data.tool !== "string"){ -const err2 = {instancePath:instancePath+"/tool",schemaPath:"#/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate199.errors = vErrors; -return errors === 0; -} - -export const ToolCancelParams = validate200; -const schema201 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"reason":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolCancelParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolCancelParams","required":["invocation_id","generation","reason"],"additionalProperties":true}; - -function validate200(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolCancelParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.reason === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "reason"},message:"must have required property '"+"reason"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err3 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.reason !== undefined){ -if(typeof data.reason !== "string"){ -const err7 = {instancePath:instancePath+"/reason",schemaPath:"#/properties/reason/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate200.errors = vErrors; -return errors === 0; -} - -export const ToolConfigureParams = validate201; -const schema202 = {"type":"object","properties":{"deny_permissions":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/ToolConfigureParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolConfigureParams","required":["deny_permissions"],"additionalProperties":true}; - -function validate201(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolConfigureParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.deny_permissions === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deny_permissions"},message:"must have required property '"+"deny_permissions"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.deny_permissions !== undefined){ -if(typeof data.deny_permissions !== "boolean"){ -const err1 = {instancePath:instancePath+"/deny_permissions",schemaPath:"#/properties/deny_permissions/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate201.errors = vErrors; -return errors === 0; -} - -export const ToolInvokeParams = validate202; -const schema203 = {"type":"object","properties":{"invocation_id":{"type":"string"},"definition":{"type":"string"},"revision":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"turn_id":{"type":"string"},"tool":{"type":"string"},"input":true,"deadline_millis":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"}},"$id":"https://whip.dev/protocol/v6/ToolInvokeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolInvokeParams","required":["invocation_id","definition","revision","generation","root_id","agent_id","turn_id","tool","input","deadline_millis"],"additionalProperties":true}; - -function validate202(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolInvokeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.definition === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "definition"},message:"must have required property '"+"definition"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.revision === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "revision"},message:"must have required property '"+"revision"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.generation === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.root_id === undefined){ -const err4 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data.agent_id === undefined){ -const err5 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "agent_id"},message:"must have required property '"+"agent_id"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data.turn_id === undefined){ -const err6 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "turn_id"},message:"must have required property '"+"turn_id"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data.tool === undefined){ -const err7 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "tool"},message:"must have required property '"+"tool"+"'"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(data.input === undefined){ -const err8 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "input"},message:"must have required property '"+"input"+"'"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(data.deadline_millis === undefined){ -const err9 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "deadline_millis"},message:"must have required property '"+"deadline_millis"+"'"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err10 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.definition !== undefined){ -if(typeof data.definition !== "string"){ -const err11 = {instancePath:instancePath+"/definition",schemaPath:"#/properties/definition/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.revision !== undefined){ -if(typeof data.revision !== "string"){ -const err12 = {instancePath:instancePath+"/revision",schemaPath:"#/properties/revision/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -if(data.generation !== undefined){ -let data3 = data.generation; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err13 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err14 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -else { -const err15 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err16 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err17 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err17]; -} -else { -vErrors.push(err17); -} -errors++; -} -} -if(data.turn_id !== undefined){ -if(typeof data.turn_id !== "string"){ -const err18 = {instancePath:instancePath+"/turn_id",schemaPath:"#/properties/turn_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err18]; -} -else { -vErrors.push(err18); -} -errors++; -} -} -if(data.tool !== undefined){ -if(typeof data.tool !== "string"){ -const err19 = {instancePath:instancePath+"/tool",schemaPath:"#/properties/tool/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err19]; -} -else { -vErrors.push(err19); -} -errors++; -} -} -if(data.deadline_millis !== undefined){ -let data8 = data.deadline_millis; -if(typeof data8 === "string"){ -if(!pattern0.test(data8)){ -const err20 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err20]; -} -else { -vErrors.push(err20); -} -errors++; -} -if(!(formats0.validate(data8))){ -const err21 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err21]; -} -else { -vErrors.push(err21); -} -errors++; -} -} -else { -const err22 = {instancePath:instancePath+"/deadline_millis",schemaPath:"#/properties/deadline_millis/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err22]; -} -else { -vErrors.push(err22); -} -errors++; -} -} -} -else { -const err23 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err23]; -} -else { -vErrors.push(err23); -} -errors++; -} -validate202.errors = vErrors; -return errors === 0; -} - -export const ToolProgressParams = validate203; -const schema204 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"text":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolProgressParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolProgressParams","required":["invocation_id","generation","text"],"additionalProperties":true}; - -function validate203(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolProgressParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.text === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "text"},message:"must have required property '"+"text"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err3 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.text !== undefined){ -if(typeof data.text !== "string"){ -const err7 = {instancePath:instancePath+"/text",schemaPath:"#/properties/text/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate203.errors = vErrors; -return errors === 0; -} - -export const ToolResultParams = validate204; -const schema205 = {"type":"object","properties":{"invocation_id":{"type":"string"},"generation":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"output":true,"error":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/ToolResultParams","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolResultParams","required":["invocation_id","generation"],"additionalProperties":true}; - -function validate204(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolResultParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.invocation_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "invocation_id"},message:"must have required property '"+"invocation_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.generation === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "generation"},message:"must have required property '"+"generation"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.invocation_id !== undefined){ -if(typeof data.invocation_id !== "string"){ -const err2 = {instancePath:instancePath+"/invocation_id",schemaPath:"#/properties/invocation_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.generation !== undefined){ -let data1 = data.generation; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err3 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err4 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/generation",schemaPath:"#/properties/generation/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.error !== undefined){ -if(typeof data.error !== "string"){ -const err6 = {instancePath:instancePath+"/error",schemaPath:"#/properties/error/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -} -else { -const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -validate204.errors = vErrors; -return errors === 0; -} - -export const ToolSchemaResult = validate205; -const schema206 = {"type":["null","array"],"items":{"type":"object","properties":{"type":{"type":"string"},"function":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":true},"required":["name","description","parameters"],"additionalProperties":true}},"required":["type","function"],"additionalProperties":true},"$id":"https://whip.dev/protocol/v6/ToolSchemaResult","$schema":"http://json-schema.org/draft-07/schema#","title":"ToolSchemaResult"}; - -function validate205(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/ToolSchemaResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema206.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -let data0 = data[i0]; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.type === undefined){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "type"},message:"must have required property '"+"type"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data0.function === undefined){ -const err2 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/required",keyword:"required",params:{missingProperty: "function"},message:"must have required property '"+"function"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data0.type !== undefined){ -if(typeof data0.type !== "string"){ -const err3 = {instancePath:instancePath+"/" + i0+"/type",schemaPath:"#/items/properties/type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data0.function !== undefined){ -let data2 = data0.function; -if(data2 && typeof data2 == "object" && !Array.isArray(data2)){ -if(data2.name === undefined){ -const err4 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "name"},message:"must have required property '"+"name"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data2.description === undefined){ -const err5 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "description"},message:"must have required property '"+"description"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data2.parameters === undefined){ -const err6 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/required",keyword:"required",params:{missingProperty: "parameters"},message:"must have required property '"+"parameters"+"'"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -if(data2.name !== undefined){ -if(typeof data2.name !== "string"){ -const err7 = {instancePath:instancePath+"/" + i0+"/function/name",schemaPath:"#/items/properties/function/properties/name/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data2.description !== undefined){ -if(typeof data2.description !== "string"){ -const err8 = {instancePath:instancePath+"/" + i0+"/function/description",schemaPath:"#/items/properties/function/properties/description/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -else { -const err9 = {instancePath:instancePath+"/" + i0+"/function",schemaPath:"#/items/properties/function/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -} -else { -const err10 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -} -validate205.errors = vErrors; -return errors === 0; -} - -export const TraceExportParams = validate206; -const schema207 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/TraceExportParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportParams","required":["root_id"],"additionalProperties":true}; - -function validate206(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TraceExportParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err2 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -} -else { -const err3 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -validate206.errors = vErrors; -return errors === 0; -} - -export const TraceExportResult = validate207; -const schema208 = {"type":"object","properties":{"content":{"type":"object","properties":{"reference_id":{"type":"string"},"digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"required":["reference_id","digest","size"],"additionalProperties":true},"spans":{"type":"integer"},"traces":{"type":"integer"}},"$id":"https://whip.dev/protocol/v6/TraceExportResult","$schema":"http://json-schema.org/draft-07/schema#","title":"TraceExportResult","required":["content","spans","traces"],"additionalProperties":true}; - -function validate207(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TraceExportResult" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.content === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "content"},message:"must have required property '"+"content"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.spans === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "spans"},message:"must have required property '"+"spans"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.traces === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "traces"},message:"must have required property '"+"traces"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.content !== undefined){ -let data0 = data.content; -if(data0 && typeof data0 == "object" && !Array.isArray(data0)){ -if(data0.reference_id === undefined){ -const err3 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "reference_id"},message:"must have required property '"+"reference_id"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data0.digest === undefined){ -const err4 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "digest"},message:"must have required property '"+"digest"+"'"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(data0.size === undefined){ -const err5 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -if(data0.reference_id !== undefined){ -if(typeof data0.reference_id !== "string"){ -const err6 = {instancePath:instancePath+"/content/reference_id",schemaPath:"#/properties/content/properties/reference_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data0.digest !== undefined){ -if(typeof data0.digest !== "string"){ -const err7 = {instancePath:instancePath+"/content/digest",schemaPath:"#/properties/content/properties/digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data0.size !== undefined){ -let data3 = data0.size; -if(typeof data3 === "string"){ -if(!pattern0.test(data3)){ -const err8 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data3))){ -const err9 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/content/size",schemaPath:"#/properties/content/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data0.media_type !== undefined){ -if(typeof data0.media_type !== "string"){ -const err11 = {instancePath:instancePath+"/content/media_type",schemaPath:"#/properties/content/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data0.source !== undefined){ -if(typeof data0.source !== "string"){ -const err12 = {instancePath:instancePath+"/content/source",schemaPath:"#/properties/content/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath:instancePath+"/content",schemaPath:"#/properties/content/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -} -if(data.spans !== undefined){ -let data6 = data.spans; -if(!((typeof data6 == "number") && (!(data6 % 1) && !isNaN(data6)))){ -const err14 = {instancePath:instancePath+"/spans",schemaPath:"#/properties/spans/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err14]; -} -else { -vErrors.push(err14); -} -errors++; -} -} -if(data.traces !== undefined){ -let data7 = data.traces; -if(!((typeof data7 == "number") && (!(data7 % 1) && !isNaN(data7)))){ -const err15 = {instancePath:instancePath+"/traces",schemaPath:"#/properties/traces/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err15]; -} -else { -vErrors.push(err15); -} -errors++; -} -} -} -else { -const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err16]; -} -else { -vErrors.push(err16); -} -errors++; -} -validate207.errors = vErrors; -return errors === 0; -} - -export const TracePageParams = validate208; -const schema209 = {"type":"object","properties":{"root_id":{"type":"string"},"trace_id":{"type":"string"},"after_seq":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"limit":{"type":"integer"},"roots_only":{"type":"boolean"}},"$id":"https://whip.dev/protocol/v6/TracePageParams","$schema":"http://json-schema.org/draft-07/schema#","title":"TracePageParams","required":["root_id"],"additionalProperties":true}; - -function validate208(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/TracePageParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.root_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err1 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -if(data.trace_id !== undefined){ -if(typeof data.trace_id !== "string"){ -const err2 = {instancePath:instancePath+"/trace_id",schemaPath:"#/properties/trace_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -} -if(data.after_seq !== undefined){ -let data2 = data.after_seq; -if(typeof data2 === "string"){ -if(!pattern0.test(data2)){ -const err3 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(!(formats0.validate(data2))){ -const err4 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -else { -const err5 = {instancePath:instancePath+"/after_seq",schemaPath:"#/properties/after_seq/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.limit !== undefined){ -let data3 = data.limit; -if(!((typeof data3 == "number") && (!(data3 % 1) && !isNaN(data3)))){ -const err6 = {instancePath:instancePath+"/limit",schemaPath:"#/properties/limit/type",keyword:"type",params:{type: "integer"},message:"must be integer"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.roots_only !== undefined){ -if(typeof data.roots_only !== "boolean"){ -const err7 = {instancePath:instancePath+"/roots_only",schemaPath:"#/properties/roots_only/type",keyword:"type",params:{type: "boolean"},message:"must be boolean"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -} -else { -const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -validate208.errors = vErrors; -return errors === 0; -} - -export const UnsubscribeParams = validate209; -const schema210 = {"type":"object","properties":{"subscription_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UnsubscribeParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UnsubscribeParams","required":["subscription_id"],"additionalProperties":true}; - -function validate209(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UnsubscribeParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.subscription_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "subscription_id"},message:"must have required property '"+"subscription_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.subscription_id !== undefined){ -if(typeof data.subscription_id !== "string"){ -const err1 = {instancePath:instancePath+"/subscription_id",schemaPath:"#/properties/subscription_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate209.errors = vErrors; -return errors === 0; -} - -export const UploadBeginParams = validate210; -const schema211 = {"type":"object","properties":{"upload_id":{"type":"string"},"root_id":{"type":"string"},"agent_id":{"type":"string"},"expected_digest":{"type":"string"},"size":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"media_type":{"type":"string"},"source":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadBeginParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadBeginParams","required":["upload_id","root_id","expected_digest","size"],"additionalProperties":true}; - -function validate210(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadBeginParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.root_id === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "root_id"},message:"must have required property '"+"root_id"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.expected_digest === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "expected_digest"},message:"must have required property '"+"expected_digest"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.size === undefined){ -const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "size"},message:"must have required property '"+"size"+"'"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err4 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -} -if(data.root_id !== undefined){ -if(typeof data.root_id !== "string"){ -const err5 = {instancePath:instancePath+"/root_id",schemaPath:"#/properties/root_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -if(data.agent_id !== undefined){ -if(typeof data.agent_id !== "string"){ -const err6 = {instancePath:instancePath+"/agent_id",schemaPath:"#/properties/agent_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.expected_digest !== undefined){ -if(typeof data.expected_digest !== "string"){ -const err7 = {instancePath:instancePath+"/expected_digest",schemaPath:"#/properties/expected_digest/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -} -if(data.size !== undefined){ -let data4 = data.size; -if(typeof data4 === "string"){ -if(!pattern0.test(data4)){ -const err8 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -if(!(formats0.validate(data4))){ -const err9 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -} -else { -const err10 = {instancePath:instancePath+"/size",schemaPath:"#/properties/size/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err10]; -} -else { -vErrors.push(err10); -} -errors++; -} -} -if(data.media_type !== undefined){ -if(typeof data.media_type !== "string"){ -const err11 = {instancePath:instancePath+"/media_type",schemaPath:"#/properties/media_type/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err11]; -} -else { -vErrors.push(err11); -} -errors++; -} -} -if(data.source !== undefined){ -if(typeof data.source !== "string"){ -const err12 = {instancePath:instancePath+"/source",schemaPath:"#/properties/source/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err12]; -} -else { -vErrors.push(err12); -} -errors++; -} -} -} -else { -const err13 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err13]; -} -else { -vErrors.push(err13); -} -errors++; -} -validate210.errors = vErrors; -return errors === 0; -} - -export const UploadChunkParams = validate211; -const schema212 = {"type":"object","properties":{"upload_id":{"type":"string"},"offset":{"type":"string","pattern":"^-?(0|[1-9][0-9]*)$","format":"int64"},"data":{"type":["string","null"],"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$","contentEncoding":"base64"}},"$id":"https://whip.dev/protocol/v6/UploadChunkParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadChunkParams","required":["upload_id","offset","data"],"additionalProperties":true}; - -function validate211(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadChunkParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.offset === undefined){ -const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "offset"},message:"must have required property '"+"offset"+"'"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -if(data.data === undefined){ -const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "data"},message:"must have required property '"+"data"+"'"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err3 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err3]; -} -else { -vErrors.push(err3); -} -errors++; -} -} -if(data.offset !== undefined){ -let data1 = data.offset; -if(typeof data1 === "string"){ -if(!pattern0.test(data1)){ -const err4 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/pattern",keyword:"pattern",params:{pattern: "^-?(0|[1-9][0-9]*)$"},message:"must match pattern \""+"^-?(0|[1-9][0-9]*)$"+"\""}; -if(vErrors === null){ -vErrors = [err4]; -} -else { -vErrors.push(err4); -} -errors++; -} -if(!(formats0.validate(data1))){ -const err5 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/format",keyword:"format",params:{format: "int64"},message:"must match format \""+"int64"+"\""}; -if(vErrors === null){ -vErrors = [err5]; -} -else { -vErrors.push(err5); -} -errors++; -} -} -else { -const err6 = {instancePath:instancePath+"/offset",schemaPath:"#/properties/offset/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err6]; -} -else { -vErrors.push(err6); -} -errors++; -} -} -if(data.data !== undefined){ -let data2 = data.data; -if((typeof data2 !== "string") && (data2 !== null)){ -const err7 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/type",keyword:"type",params:{type: schema212.properties.data.type},message:"must be string,null"}; -if(vErrors === null){ -vErrors = [err7]; -} -else { -vErrors.push(err7); -} -errors++; -} -if(typeof data2 === "string"){ -if(!pattern52.test(data2)){ -const err8 = {instancePath:instancePath+"/data",schemaPath:"#/properties/data/pattern",keyword:"pattern",params:{pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"},message:"must match pattern \""+"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"+"\""}; -if(vErrors === null){ -vErrors = [err8]; -} -else { -vErrors.push(err8); -} -errors++; -} -} -} -} -else { -const err9 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err9]; -} -else { -vErrors.push(err9); -} -errors++; -} -validate211.errors = vErrors; -return errors === 0; -} - -export const UploadFinishParams = validate212; -const schema213 = {"type":"object","properties":{"upload_id":{"type":"string"}},"$id":"https://whip.dev/protocol/v6/UploadFinishParams","$schema":"http://json-schema.org/draft-07/schema#","title":"UploadFinishParams","required":["upload_id"],"additionalProperties":true}; - -function validate212(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UploadFinishParams" */; -let vErrors = null; -let errors = 0; -if(data && typeof data == "object" && !Array.isArray(data)){ -if(data.upload_id === undefined){ -const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "upload_id"},message:"must have required property '"+"upload_id"+"'"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(data.upload_id !== undefined){ -if(typeof data.upload_id !== "string"){ -const err1 = {instancePath:instancePath+"/upload_id",schemaPath:"#/properties/upload_id/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -else { -const err2 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"}; -if(vErrors === null){ -vErrors = [err2]; -} -else { -vErrors.push(err2); -} -errors++; -} -validate212.errors = vErrors; -return errors === 0; -} - -export const UserHistoryResult = validate213; -const schema214 = {"type":["null","array"],"items":{"type":"string"},"$id":"https://whip.dev/protocol/v6/UserHistoryResult","$schema":"http://json-schema.org/draft-07/schema#","title":"UserHistoryResult"}; - -function validate213(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){ -/*# sourceURL="https://whip.dev/protocol/v6/UserHistoryResult" */; -let vErrors = null; -let errors = 0; -if((data !== null) && (!(Array.isArray(data)))){ -const err0 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: schema214.type},message:"must be null,array"}; -if(vErrors === null){ -vErrors = [err0]; -} -else { -vErrors.push(err0); -} -errors++; -} -if(Array.isArray(data)){ -const len0 = data.length; -for(let i0=0; i0<len0; i0++){ -if(typeof data[i0] !== "string"){ -const err1 = {instancePath:instancePath+"/" + i0,schemaPath:"#/items/type",keyword:"type",params:{type: "string"},message:"must be string"}; -if(vErrors === null){ -vErrors = [err1]; -} -else { -vErrors.push(err1); -} -errors++; -} -} -} -validate213.errors = vErrors; -return errors === 0; -} diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 9196a302e..32767162c 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -14,8 +14,9 @@ }, "scripts": { "generate": "go run ../../cmd/whip-contract -out schema && node scripts/generate.mjs", - "check:drift": "go run ../../cmd/whip-contract -out schema -check && node scripts/generate.mjs --check", - "check": "tsc --noEmit && node --disallow-code-generation-from-strings --test scripts/interop.test.mjs && npm run check:drift" + "check:drift": "node scripts/check.mjs", + "check": "npm run check:drift && tsc --noEmit && node --disallow-code-generation-from-strings --test scripts/interop.test.mjs && node --test scripts/initialization.test.mjs", + "prepack": "npm run check:drift" }, "devDependencies": { "json-schema-to-typescript": "15.0.4", diff --git a/packages/protocol/schema/Accepted.json b/packages/protocol/schema/Accepted.json deleted file mode 100644 index 72f42dc8d..000000000 --- a/packages/protocol/schema/Accepted.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "accepted": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/Accepted", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Accepted", - "required": [ - "accepted" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/AgentCancelParams.json b/packages/protocol/schema/AgentCancelParams.json deleted file mode 100644 index 4d414896e..000000000 --- a/packages/protocol/schema/AgentCancelParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "turn_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/AgentCancelParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentCancelParams", - "required": [ - "id", - "turn_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/AgentInputParams.json b/packages/protocol/schema/AgentInputParams.json deleted file mode 100644 index b203e8a08..000000000 --- a/packages/protocol/schema/AgentInputParams.json +++ /dev/null @@ -1,168 +0,0 @@ -{ - "type": "object", - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "text": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "text": { - "type": "string" - }, - "image_url": { - "type": [ - "null", - "object" - ], - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false - }, - "w": { - "type": "integer" - }, - "h": { - "type": "integer" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": [ - "image", - "text" - ] - }, - "content": { - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "name": { - "type": "string" - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/AgentInputParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentInputParams", - "required": [ - "id", - "text" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/AgentListResult.json b/packages/protocol/schema/AgentListResult.json deleted file mode 100644 index 185170287..000000000 --- a/packages/protocol/schema/AgentListResult.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "last_turn": { - "type": [ - "null", - "object" - ], - "properties": { - "turn_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "event_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "error": { - "type": "string" - }, - "error_truncated": { - "type": "boolean" - }, - "error_details": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "model_calls": { - "type": "integer" - }, - "compactions": { - "type": "integer" - }, - "last_activity_at": { - "type": "string" - } - }, - "required": [ - "status", - "event_seq" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "report": { - "type": "string" - }, - "status": { - "type": "string" - }, - "pending_mail": { - "type": "integer" - }, - "lifecycle_phase": { - "type": "string" - }, - "blocking_reason": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "allowed_controls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "execution_engine", - "id", - "root_id", - "parent_id", - "name", - "model", - "provider", - "effort", - "cwd", - "report", - "status", - "pending_mail", - "lifecycle_phase", - "blocking_reason", - "terminal_cause", - "allowed_controls" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/AgentListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentListResult" -} diff --git a/packages/protocol/schema/AgentSubmitResult.json b/packages/protocol/schema/AgentSubmitResult.json deleted file mode 100644 index 83df1d80d..000000000 --- a/packages/protocol/schema/AgentSubmitResult.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "type": "object", - "properties": { - "agent_id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "status": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/AgentSubmitResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentSubmitResult", - "required": [ - "agent_id", - "inbox_seq", - "status" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/AgentTranscriptResult.json b/packages/protocol/schema/AgentTranscriptResult.json deleted file mode 100644 index 3f370ee4a..000000000 --- a/packages/protocol/schema/AgentTranscriptResult.json +++ /dev/null @@ -1,1183 +0,0 @@ -{ - "type": "object", - "properties": { - "accounting": { - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "unknown_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "scope", - "revision", - "reported_cost_micros", - "estimated_cost_micros", - "reported_cost_calls", - "estimated_cost_calls", - "unknown_cost_calls", - "reported_calls", - "estimated_calls", - "pending_calls" - ], - "additionalProperties": false - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "agent": { - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "last_turn": { - "type": [ - "null", - "object" - ], - "properties": { - "turn_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "event_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "error": { - "type": "string" - }, - "error_truncated": { - "type": "boolean" - }, - "error_details": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "model_calls": { - "type": "integer" - }, - "compactions": { - "type": "integer" - }, - "last_activity_at": { - "type": "string" - } - }, - "required": [ - "status", - "event_seq" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "report": { - "type": "string" - }, - "status": { - "type": "string" - }, - "pending_mail": { - "type": "integer" - }, - "lifecycle_phase": { - "type": "string" - }, - "blocking_reason": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "allowed_controls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "execution_engine", - "id", - "root_id", - "parent_id", - "name", - "model", - "provider", - "effort", - "cwd", - "report", - "status", - "pending_mail", - "lifecycle_phase", - "blocking_reason", - "terminal_cause", - "allowed_controls" - ], - "additionalProperties": false - }, - "page": { - "type": "object", - "properties": { - "history_revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "through_seq": { - "type": "integer" - }, - "next_seq": { - "type": "integer" - }, - "has_more": { - "type": "boolean" - }, - "messages": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "presentation": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - }, - "context_part_index": { - "type": "integer" - }, - "screenshot_part_index": { - "type": [ - "null", - "integer" - ] - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count", - "context_part_index" - ], - "additionalProperties": false - }, - "version": { - "type": "integer" - }, - "turn_id": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "start": { - "type": "integer" - }, - "end": { - "type": "integer" - }, - "text": { - "type": "string" - }, - "tool_name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "call_id": { - "type": "string" - }, - "hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "status": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "error": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "invocation_id", - "name", - "status" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "id", - "kind" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "version" - ], - "additionalProperties": false - }, - "role": { - "type": "string" - }, - "authored": { - "type": "boolean" - }, - "sent_at": { - "type": [ - "null", - "string" - ] - }, - "seq": { - "type": "integer" - }, - "message": { - "type": [ - "null", - "object" - ], - "properties": { - "presentation": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - }, - "context_part_index": { - "type": "integer" - }, - "screenshot_part_index": { - "type": [ - "null", - "integer" - ] - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count", - "context_part_index" - ], - "additionalProperties": false - }, - "version": { - "type": "integer" - }, - "turn_id": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "start": { - "type": "integer" - }, - "end": { - "type": "integer" - }, - "text": { - "type": "string" - }, - "tool_name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "call_id": { - "type": "string" - }, - "hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "status": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "error": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "invocation_id", - "name", - "status" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "id", - "kind" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "version" - ], - "additionalProperties": false - }, - "role": { - "type": "string" - }, - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "text": { - "type": "string" - }, - "image_url": { - "type": [ - "null", - "object" - ], - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false - }, - "w": { - "type": "integer" - }, - "h": { - "type": "integer" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - } - ] - }, - "tool_calls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "arguments": { - "type": "string" - } - }, - "required": [ - "name", - "arguments" - ], - "additionalProperties": false - }, - "duration_ms": { - "type": "integer" - }, - "exit_code": { - "type": "integer" - } - }, - "required": [ - "id", - "type", - "function" - ], - "additionalProperties": false - } - }, - "tool_call_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "authored": { - "type": "boolean" - }, - "sent_at": { - "type": [ - "null", - "string" - ] - }, - "usage": { - "type": [ - "null", - "object" - ], - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - }, - "model": { - "type": "string" - }, - "rewound_from": { - "type": "string" - }, - "call_id": { - "type": "string" - } - }, - "required": [ - "role", - "content" - ], - "additionalProperties": false - }, - "body": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "seq" - ], - "additionalProperties": false - } - } - }, - "required": [ - "history_revision", - "through_seq", - "next_seq", - "has_more", - "messages" - ], - "additionalProperties": false - }, - "presentation": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "payload": true - }, - "required": [ - "seq", - "kind", - "payload" - ], - "additionalProperties": false - } - }, - "inbox": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "delivery_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "origin": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "steer_turn_id": { - "type": "string" - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "text": { - "type": "string" - }, - "truncated": { - "type": "boolean" - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "content": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - }, - "attachment_count": { - "type": "integer" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "status": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "root_id", - "agent_id", - "seq", - "kind", - "status", - "payload" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/AgentTranscriptResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "AgentTranscriptResult", - "required": [ - "cursor", - "agent", - "page" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ArchiveParams.json b/packages/protocol/schema/ArchiveParams.json deleted file mode 100644 index 8bbc1abfe..000000000 --- a/packages/protocol/schema/ArchiveParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "archived": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ArchiveParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ArchiveParams", - "required": [ - "archived" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ArchiveResult.json b/packages/protocol/schema/ArchiveResult.json deleted file mode 100644 index 4c361aa62..000000000 --- a/packages/protocol/schema/ArchiveResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "archived": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ArchiveResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ArchiveResult", - "required": [ - "archived" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BoundedTranscriptPage.json b/packages/protocol/schema/BoundedTranscriptPage.json deleted file mode 100644 index 0ea215f6a..000000000 --- a/packages/protocol/schema/BoundedTranscriptPage.json +++ /dev/null @@ -1,662 +0,0 @@ -{ - "type": "object", - "properties": { - "history_revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "through_seq": { - "type": "integer" - }, - "next_seq": { - "type": "integer" - }, - "has_more": { - "type": "boolean" - }, - "messages": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "presentation": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - }, - "context_part_index": { - "type": "integer" - }, - "screenshot_part_index": { - "type": [ - "null", - "integer" - ] - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count", - "context_part_index" - ], - "additionalProperties": false - }, - "version": { - "type": "integer" - }, - "turn_id": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "start": { - "type": "integer" - }, - "end": { - "type": "integer" - }, - "text": { - "type": "string" - }, - "tool_name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "call_id": { - "type": "string" - }, - "hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "status": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "error": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "invocation_id", - "name", - "status" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "id", - "kind" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "version" - ], - "additionalProperties": false - }, - "role": { - "type": "string" - }, - "authored": { - "type": "boolean" - }, - "sent_at": { - "type": [ - "null", - "string" - ] - }, - "seq": { - "type": "integer" - }, - "message": { - "type": [ - "null", - "object" - ], - "properties": { - "presentation": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - }, - "context_part_index": { - "type": "integer" - }, - "screenshot_part_index": { - "type": [ - "null", - "integer" - ] - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count", - "context_part_index" - ], - "additionalProperties": false - }, - "version": { - "type": "integer" - }, - "turn_id": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "start": { - "type": "integer" - }, - "end": { - "type": "integer" - }, - "text": { - "type": "string" - }, - "tool_name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "call_id": { - "type": "string" - }, - "hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "status": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "error": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "invocation_id", - "name", - "status" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "id", - "kind" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "version" - ], - "additionalProperties": false - }, - "role": { - "type": "string" - }, - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "text": { - "type": "string" - }, - "image_url": { - "type": [ - "null", - "object" - ], - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false - }, - "w": { - "type": "integer" - }, - "h": { - "type": "integer" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - } - ] - }, - "tool_calls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "arguments": { - "type": "string" - } - }, - "required": [ - "name", - "arguments" - ], - "additionalProperties": false - }, - "duration_ms": { - "type": "integer" - }, - "exit_code": { - "type": "integer" - } - }, - "required": [ - "id", - "type", - "function" - ], - "additionalProperties": false - } - }, - "tool_call_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "authored": { - "type": "boolean" - }, - "sent_at": { - "type": [ - "null", - "string" - ] - }, - "usage": { - "type": [ - "null", - "object" - ], - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - }, - "model": { - "type": "string" - }, - "rewound_from": { - "type": "string" - }, - "call_id": { - "type": "string" - } - }, - "required": [ - "role", - "content" - ], - "additionalProperties": false - }, - "body": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "seq" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/BoundedTranscriptPage", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BoundedTranscriptPage", - "required": [ - "history_revision", - "through_seq", - "next_seq", - "has_more", - "messages" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserCommand.json b/packages/protocol/schema/BrowserCommand.json deleted file mode 100644 index cd1bb775e..000000000 --- a/packages/protocol/schema/BrowserCommand.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "scope": { - "type": "object", - "properties": { - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "rights": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "provider_id", - "provider_epoch", - "tab_id", - "tab_generation", - "profile_id", - "rights" - ], - "additionalProperties": false - }, - "expected_document": { - "type": "string" - }, - "deadline_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "arguments": true - }, - "$id": "https://whip.dev/protocol/v6/BrowserCommand", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserCommand", - "required": [ - "command_id", - "operation_id", - "root_id", - "agent_id", - "provider_epoch", - "scope", - "deadline_millis", - "kind", - "arguments" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserCommandCancel.json b/packages/protocol/schema/BrowserCommandCancel.json deleted file mode 100644 index 86e7f890b..000000000 --- a/packages/protocol/schema/BrowserCommandCancel.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserCommandCancel", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserCommandCancel", - "required": [ - "command_id", - "root_id", - "provider_epoch", - "attachment_generation", - "reason" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserCommandResultParams.json b/packages/protocol/schema/BrowserCommandResultParams.json deleted file mode 100644 index 45ebeeba0..000000000 --- a/packages/protocol/schema/BrowserCommandResultParams.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "document_revision": { - "type": "string" - }, - "result": true, - "error": { - "type": [ - "null", - "object" - ], - "properties": { - "kind": { - "type": "string" - }, - "message": { - "type": "string" - } - }, - "required": [ - "kind", - "message" - ], - "additionalProperties": false - }, - "screenshot": { - "type": [ - "null", - "object" - ], - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserCommandResultParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserCommandResultParams", - "required": [ - "command_id", - "root_id", - "provider_epoch", - "attachment_generation", - "document_revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserDriverParams.json b/packages/protocol/schema/BrowserDriverParams.json deleted file mode 100644 index 855072f97..000000000 --- a/packages/protocol/schema/BrowserDriverParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "driver": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserDriverParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserDriverParams", - "required": [ - "driver" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserInventoryRequest.json b/packages/protocol/schema/BrowserInventoryRequest.json deleted file mode 100644 index 0bc1f2704..000000000 --- a/packages/protocol/schema/BrowserInventoryRequest.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "type": "object", - "properties": { - "request_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tabs": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - } - }, - "required": [ - "tab_id", - "tab_generation" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserInventoryRequest", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserInventoryRequest", - "required": [ - "request_id", - "root_id", - "agent_id", - "provider_id", - "provider_epoch", - "tabs" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserInventoryResultParams.json b/packages/protocol/schema/BrowserInventoryResultParams.json deleted file mode 100644 index 1fc0c5469..000000000 --- a/packages/protocol/schema/BrowserInventoryResultParams.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "type": "object", - "properties": { - "request_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tabs": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "document_revision": { - "type": "string" - }, - "url": { - "type": "string" - }, - "title": { - "type": "string" - }, - "state": { - "type": "string" - }, - "requestable": { - "type": "boolean" - }, - "attachment_id": { - "type": "string" - } - }, - "required": [ - "tab_id", - "tab_generation", - "document_revision", - "url", - "title", - "state", - "requestable" - ], - "additionalProperties": false - } - }, - "error": { - "type": [ - "null", - "object" - ], - "properties": { - "kind": { - "type": "string" - }, - "message": { - "type": "string" - } - }, - "required": [ - "kind", - "message" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserInventoryResultParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserInventoryResultParams", - "required": [ - "request_id", - "root_id", - "provider_epoch", - "tabs" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserProviderBindParams.json b/packages/protocol/schema/BrowserProviderBindParams.json deleted file mode 100644 index 4e10e193e..000000000 --- a/packages/protocol/schema/BrowserProviderBindParams.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "type": "object", - "properties": { - "availability": { - "type": "boolean" - }, - "root_id": { - "type": "string" - }, - "version": { - "type": "integer" - }, - "desktop_id": { - "type": "string" - }, - "window_id": { - "type": "string" - }, - "offer_revision": { - "type": "string" - }, - "create_profile_id": { - "type": "string" - }, - "expected_provider_epoch": { - "type": "string" - }, - "offered_tabs": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "document_revision": { - "type": "string" - }, - "url": { - "type": "string" - }, - "title": { - "type": "string" - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "tab_id", - "tab_generation", - "profile_id" - ], - "additionalProperties": false - } - }, - "offered_preview_hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserProviderBindParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserProviderBindParams", - "required": [ - "root_id", - "version", - "desktop_id", - "window_id", - "offer_revision", - "create_profile_id", - "offered_tabs", - "offered_preview_hosts" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserProviderBindResult.json b/packages/protocol/schema/BrowserProviderBindResult.json deleted file mode 100644 index 73467a2b6..000000000 --- a/packages/protocol/schema/BrowserProviderBindResult.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "version": { - "type": "integer" - }, - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserProviderBindResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserProviderBindResult", - "required": [ - "version", - "provider_id", - "provider_epoch" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserProviderEventParams.json b/packages/protocol/schema/BrowserProviderEventParams.json deleted file mode 100644 index ac6cf845e..000000000 --- a/packages/protocol/schema/BrowserProviderEventParams.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "sequence": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "operation_id": { - "type": "string" - }, - "document_revision": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "method": { - "type": "string" - }, - "params": true, - "url": { - "type": "string" - }, - "title": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserProviderEventParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserProviderEventParams", - "required": [ - "root_id", - "provider_epoch", - "tab_id", - "tab_generation", - "attachment_id", - "attachment_generation", - "sequence", - "document_revision", - "kind" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserProviderRevoked.json b/packages/protocol/schema/BrowserProviderRevoked.json deleted file mode 100644 index 316a23855..000000000 --- a/packages/protocol/schema/BrowserProviderRevoked.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserProviderRevoked", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserProviderRevoked", - "required": [ - "root_id", - "provider_id", - "provider_epoch", - "reason" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserProviderUnbindParams.json b/packages/protocol/schema/BrowserProviderUnbindParams.json deleted file mode 100644 index 741ad7011..000000000 --- a/packages/protocol/schema/BrowserProviderUnbindParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserProviderUnbindParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserProviderUnbindParams", - "required": [ - "root_id", - "provider_epoch" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BrowserStatusResult.json b/packages/protocol/schema/BrowserStatusResult.json deleted file mode 100644 index 15928bd26..000000000 --- a/packages/protocol/schema/BrowserStatusResult.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "driver": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/BrowserStatusResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BrowserStatusResult", - "required": [ - "enabled" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BudgetCapParams.json b/packages/protocol/schema/BudgetCapParams.json deleted file mode 100644 index d00f4fa33..000000000 --- a/packages/protocol/schema/BudgetCapParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "limit": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/BudgetCapParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BudgetCapParams", - "required": [ - "id", - "kind", - "limit" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/BudgetState.json b/packages/protocol/schema/BudgetState.json deleted file mode 100644 index 4b74d3546..000000000 --- a/packages/protocol/schema/BudgetState.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "limit": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "remaining": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "uncertain": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "incomplete": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/BudgetState", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BudgetState", - "required": [ - "kind", - "limit", - "used", - "reserved", - "remaining", - "uncertain", - "incomplete" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CancelParams.json b/packages/protocol/schema/CancelParams.json deleted file mode 100644 index 2de07790a..000000000 --- a/packages/protocol/schema/CancelParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "turn_id": { - "type": "string" - }, - "target_command_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CancelParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CancelParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/CapabilityRecord.json b/packages/protocol/schema/CapabilityRecord.json deleted file mode 100644 index 00621896e..000000000 --- a/packages/protocol/schema/CapabilityRecord.json +++ /dev/null @@ -1,208 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "issuer_agent_id": { - "type": "string" - }, - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "scopes": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "file_scope": { - "type": "string" - }, - "file_issuer_id": { - "type": "string" - }, - "file_issuer_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "mcp": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "server": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "definition": { - "type": "string" - } - }, - "required": [ - "server", - "tool", - "definition" - ], - "additionalProperties": false - } - }, - "mcp_all": { - "type": "boolean" - }, - "browser": { - "type": [ - "null", - "object" - ], - "properties": { - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "rights": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "provider_id", - "provider_epoch", - "tab_id", - "tab_generation", - "profile_id", - "rights" - ], - "additionalProperties": false - }, - "browser_issuer_id": { - "type": "string" - }, - "browser_issuer_generation": { - "type": "integer" - }, - "browser_delegation_only": { - "type": "boolean" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CapabilityRecord", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CapabilityRecord", - "required": [ - "id", - "root_id", - "agent_id", - "issuer_agent_id", - "operations", - "scopes", - "mcp", - "mcp_all", - "generation", - "status", - "expires_at", - "created_at", - "updated_at" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CatalogResult.json b/packages/protocol/schema/CatalogResult.json deleted file mode 100644 index a513c5610..000000000 --- a/packages/protocol/schema/CatalogResult.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "type": "object", - "properties": { - "themes": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "dark": { - "type": "boolean" - }, - "source": { - "type": "string" - } - }, - "required": [ - "id", - "name", - "dark", - "source" - ], - "additionalProperties": false - } - }, - "errors": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "file": { - "type": "string" - }, - "message": { - "type": "string" - } - }, - "required": [ - "file", - "message" - ], - "additionalProperties": false - } - }, - "truncated": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/CatalogResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CatalogResult", - "required": [ - "themes", - "errors", - "truncated" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CatalogRevision.json b/packages/protocol/schema/CatalogRevision.json deleted file mode 100644 index 7d0556169..000000000 --- a/packages/protocol/schema/CatalogRevision.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/CatalogRevision", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CatalogRevision", - "required": [ - "revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CheckpointParams.json b/packages/protocol/schema/CheckpointParams.json deleted file mode 100644 index b6906cc68..000000000 --- a/packages/protocol/schema/CheckpointParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "reason": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CheckpointParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CheckpointParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ClearHistoryParams.json b/packages/protocol/schema/ClearHistoryParams.json deleted file mode 100644 index 21cb2b794..000000000 --- a/packages/protocol/schema/ClearHistoryParams.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "object", - "properties": { - "expected_revision": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/ClearHistoryParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ClearHistoryParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/CommandParams.json b/packages/protocol/schema/CommandParams.json deleted file mode 100644 index 000ae77b3..000000000 --- a/packages/protocol/schema/CommandParams.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "payload": true - }, - "$id": "https://whip.dev/protocol/v6/CommandParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CommandParams", - "required": [ - "command_id", - "scope", - "operation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CommandResult.json b/packages/protocol/schema/CommandResult.json deleted file mode 100644 index c5491b428..000000000 --- a/packages/protocol/schema/CommandResult.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "type": "object", - "properties": { - "content": { - "type": [ - "null", - "object" - ], - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "operation": { - "type": "string" - }, - "result": true, - "failure": { - "type": [ - "null", - "object" - ], - "properties": { - "data": { - "type": [ - "null", - "object" - ], - "properties": { - "kind": { - "type": "string" - } - }, - "required": [ - "kind" - ], - "additionalProperties": false - }, - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "required": [ - "code", - "message" - ], - "additionalProperties": false - }, - "command_id": { - "type": "string" - }, - "ingress_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CommandResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CommandResult", - "required": [ - "operation", - "command_id", - "ingress_seq", - "status" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CommandStatusParams.json b/packages/protocol/schema/CommandStatusParams.json deleted file mode 100644 index d276dd8a2..000000000 --- a/packages/protocol/schema/CommandStatusParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CommandStatusParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CommandStatusParams", - "required": [ - "command_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompactionListResult.json b/packages/protocol/schema/CompactionListResult.json deleted file mode 100644 index 481b60dd3..000000000 --- a/packages/protocol/schema/CompactionListResult.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "seq": { - "type": "integer" - }, - "cutoff": { - "type": "integer" - }, - "summary": { - "type": "string" - } - }, - "required": [ - "seq", - "cutoff", - "summary" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/CompactionListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompactionListResult" -} diff --git a/packages/protocol/schema/CompactionParams.json b/packages/protocol/schema/CompactionParams.json deleted file mode 100644 index 16f3fb47e..000000000 --- a/packages/protocol/schema/CompactionParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CompactionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompactionParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompactionResult.json b/packages/protocol/schema/CompactionResult.json deleted file mode 100644 index 4694e1e81..000000000 --- a/packages/protocol/schema/CompactionResult.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "type": "object", - "properties": { - "cutoff": { - "type": "integer" - }, - "model": { - "type": "string" - }, - "usage": { - "type": "object", - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/CompactionResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompactionResult", - "required": [ - "cutoff", - "usage" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompactionRetryResult.json b/packages/protocol/schema/CompactionRetryResult.json deleted file mode 100644 index 484deee55..000000000 --- a/packages/protocol/schema/CompactionRetryResult.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "undone": { - "type": "boolean" - }, - "sequence": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/CompactionRetryResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompactionRetryResult", - "required": [ - "undone" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompactionSettingsResult.json b/packages/protocol/schema/CompactionSettingsResult.json deleted file mode 100644 index 4fd14bfe4..000000000 --- a/packages/protocol/schema/CompactionSettingsResult.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "builtin_default": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/CompactionSettingsResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompactionSettingsResult", - "required": [ - "builtin_default" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompletionParams.json b/packages/protocol/schema/CompletionParams.json deleted file mode 100644 index b9a970be6..000000000 --- a/packages/protocol/schema/CompletionParams.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "limit": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/CompletionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompletionParams", - "required": [ - "root_id", - "kind", - "prefix", - "limit" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CompletionResult.json b/packages/protocol/schema/CompletionResult.json deleted file mode 100644 index 3ec73b670..000000000 --- a/packages/protocol/schema/CompletionResult.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "type": "object", - "properties": { - "warnings": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "candidates": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": [ - "text", - "description" - ], - "additionalProperties": false - } - }, - "truncated": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/CompletionResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CompletionResult", - "required": [ - "candidates", - "truncated" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ComputerAppParams.json b/packages/protocol/schema/ComputerAppParams.json deleted file mode 100644 index 9eeead5bd..000000000 --- a/packages/protocol/schema/ComputerAppParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "app": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ComputerAppParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ComputerAppParams", - "required": [ - "app" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ComputerStatusResult.json b/packages/protocol/schema/ComputerStatusResult.json deleted file mode 100644 index 80ba4012d..000000000 --- a/packages/protocol/schema/ComputerStatusResult.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "default_deny": { - "type": "boolean" - }, - "allowed": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "denied": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "session_allowed": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "session_denied": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/ComputerStatusResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ComputerStatusResult", - "required": [ - "enabled", - "default_deny", - "allowed", - "denied", - "session_allowed", - "session_denied" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ConfigurationUpdate.json b/packages/protocol/schema/ConfigurationUpdate.json deleted file mode 100644 index 15abf5ae1..000000000 --- a/packages/protocol/schema/ConfigurationUpdate.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "type": "object", - "properties": { - "default_execution_engine": { - "type": [ - "null", - "string" - ] - }, - "disabled_providers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "remote_hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "runtime_id": { - "type": "string" - }, - "connect_on_launch": { - "type": "boolean" - } - }, - "required": [ - "id", - "name", - "url", - "runtime_id", - "connect_on_launch" - ], - "additionalProperties": false - } - }, - "import_claude": { - "type": [ - "null", - "boolean" - ] - }, - "import_codex": { - "type": [ - "null", - "boolean" - ] - }, - "brand_icons": { - "type": [ - "null", - "boolean" - ] - }, - "revision": { - "type": "string" - }, - "default_model": { - "type": [ - "null", - "string" - ] - }, - "default_provider": { - "type": [ - "null", - "string" - ] - }, - "default_effort": { - "type": [ - "null", - "string" - ] - }, - "default_permission_mode": { - "type": [ - "null", - "string" - ] - }, - "compact_model": { - "type": [ - "null", - "string" - ] - }, - "compact_provider": { - "type": [ - "null", - "string" - ] - }, - "compact_percent": { - "type": [ - "null", - "integer" - ] - }, - "goal_max_rounds": { - "type": [ - "null", - "integer" - ] - }, - "max_retries": { - "type": [ - "null", - "integer" - ] - } - }, - "$id": "https://whip.dev/protocol/v6/ConfigurationUpdate", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ConfigurationUpdate", - "required": [ - "revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ContentEventPayload.json b/packages/protocol/schema/ContentEventPayload.json deleted file mode 100644 index fc9c9fbd7..000000000 --- a/packages/protocol/schema/ContentEventPayload.json +++ /dev/null @@ -1,254 +0,0 @@ -{ - "type": "object", - "properties": { - "part_id": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - }, - "accounting": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "unknown_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "scope", - "revision", - "reported_cost_micros", - "estimated_cost_micros", - "reported_cost_calls", - "estimated_cost_calls", - "unknown_cost_calls", - "reported_calls", - "estimated_calls", - "pending_calls" - ], - "additionalProperties": false - }, - "usage": { - "type": [ - "null", - "object" - ], - "properties": { - "used": { - "type": "integer" - }, - "size": { - "type": "integer" - }, - "usage": { - "type": "object", - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "used", - "size", - "usage" - ], - "additionalProperties": false - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "invocation_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "host_status": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "text": { - "type": "string" - }, - "args": { - "type": "string" - }, - "result": { - "type": "string" - }, - "content": { - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "truncated": { - "type": "boolean", - "const": true - } - }, - "$id": "https://whip.dev/protocol/v6/ContentEventPayload", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ContentEventPayload", - "required": [ - "content", - "truncated" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ContentHandle.json b/packages/protocol/schema/ContentHandle.json deleted file mode 100644 index f45ce4e5f..000000000 --- a/packages/protocol/schema/ContentHandle.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ContentHandle", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ContentHandle", - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ContentReadParams.json b/packages/protocol/schema/ContentReadParams.json deleted file mode 100644 index 3a95a3fb1..000000000 --- a/packages/protocol/schema/ContentReadParams.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "reference_id": { - "type": "string" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ContentReadParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ContentReadParams", - "required": [ - "root_id", - "reference_id", - "offset", - "limit" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ContentReadResult.json b/packages/protocol/schema/ContentReadResult.json deleted file mode 100644 index ee4d5eaf3..000000000 --- a/packages/protocol/schema/ContentReadResult.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "type": "object", - "properties": { - "data": { - "type": [ - "string", - "null" - ], - "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", - "contentEncoding": "base64" - }, - "content": { - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/ContentReadResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ContentReadResult", - "required": [ - "data", - "content" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ContextAuditResult.json b/packages/protocol/schema/ContextAuditResult.json deleted file mode 100644 index e54473ec1..000000000 --- a/packages/protocol/schema/ContextAuditResult.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "type": "object", - "properties": { - "working_directory": { - "type": "string" - }, - "rows": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "bytes": { - "type": "integer" - }, - "note": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/ContextAuditResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ContextAuditResult", - "required": [ - "working_directory", - "rows" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/CreateSessionParams.json b/packages/protocol/schema/CreateSessionParams.json deleted file mode 100644 index 82316b1bb..000000000 --- a/packages/protocol/schema/CreateSessionParams.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "permission_mode": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/CreateSessionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CreateSessionParams", - "required": [ - "kind", - "cwd", - "model", - "provider" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/DefinitionList.json b/packages/protocol/schema/DefinitionList.json deleted file mode 100644 index bde6a6b98..000000000 --- a/packages/protocol/schema/DefinitionList.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "type": "object", - "properties": { - "items": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "built_in": { - "type": "boolean" - }, - "registered_by": { - "type": "string" - }, - "created_at": { - "type": "string" - } - }, - "required": [ - "id", - "revision", - "built_in", - "registered_by", - "created_at" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/DefinitionList", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DefinitionList", - "required": [ - "items" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/DefinitionParams.json b/packages/protocol/schema/DefinitionParams.json deleted file mode 100644 index 19d9726c7..000000000 --- a/packages/protocol/schema/DefinitionParams.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "revision": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/DefinitionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DefinitionParams", - "required": [ - "id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/DefinitionRecord.json b/packages/protocol/schema/DefinitionRecord.json deleted file mode 100644 index dd4f877cb..000000000 --- a/packages/protocol/schema/DefinitionRecord.json +++ /dev/null @@ -1,422 +0,0 @@ -{ - "type": "object", - "properties": { - "definition": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "instructions": { - "type": "object", - "properties": { - "persona": { - "type": "string" - }, - "rules": { - "type": "string" - }, - "project_files": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "skill_discovery": { - "type": "boolean" - }, - "standing_instructions": { - "type": "boolean" - } - }, - "required": [ - "persona", - "rules", - "project_files", - "skill_discovery", - "standing_instructions" - ], - "additionalProperties": false - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "model": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - } - }, - "required": [ - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "compaction": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "threshold": { - "type": "number" - } - }, - "required": [ - "model", - "provider", - "threshold" - ], - "additionalProperties": false - }, - "mcp": { - "type": "object", - "properties": { - "servers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "servers" - ], - "additionalProperties": false - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "input_schema": true, - "output_schema": true, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "name", - "description", - "input_schema", - "output_schema", - "timeout_millis" - ], - "additionalProperties": false - } - }, - "output": true, - "children": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "instructions": { - "type": [ - "null", - "object" - ], - "properties": { - "persona": { - "type": "string" - }, - "rules": { - "type": "string" - }, - "project_files": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "skill_discovery": { - "type": "boolean" - }, - "standing_instructions": { - "type": "boolean" - } - }, - "required": [ - "persona", - "rules", - "project_files", - "skill_discovery", - "standing_instructions" - ], - "additionalProperties": false - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "model": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - } - }, - "required": [ - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - }, - "output": true - }, - "required": [ - "instructions", - "modules", - "capabilities", - "tools", - "model", - "budgets", - "report", - "output" - ], - "additionalProperties": false - } - }, - "surface": { - "type": "object", - "properties": { - "auto_title": { - "type": "boolean" - }, - "goal_loop": { - "type": "boolean" - } - }, - "required": [ - "auto_title", - "goal_loop" - ], - "additionalProperties": false - }, - "hooks": { - "type": [ - "null", - "object" - ], - "properties": { - "before_tool": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - }, - "before_spawn": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - }, - "turn_start": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - } - }, - "required": [ - "before_tool", - "before_spawn", - "turn_start" - ], - "additionalProperties": false - } - }, - "required": [ - "id", - "instructions", - "modules", - "capabilities", - "model", - "compaction", - "mcp", - "tools", - "output", - "children", - "surface", - "hooks" - ], - "additionalProperties": false - }, - "revision": { - "type": "string" - }, - "built_in": { - "type": "boolean" - }, - "registered_by": { - "type": "string" - }, - "created_at": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/DefinitionRecord", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DefinitionRecord", - "required": [ - "definition", - "revision", - "built_in", - "registered_by", - "created_at" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/DefinitionRegisterParams.json b/packages/protocol/schema/DefinitionRegisterParams.json deleted file mode 100644 index c9200272c..000000000 --- a/packages/protocol/schema/DefinitionRegisterParams.json +++ /dev/null @@ -1,406 +0,0 @@ -{ - "type": "object", - "properties": { - "definition": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "instructions": { - "type": "object", - "properties": { - "persona": { - "type": "string" - }, - "rules": { - "type": "string" - }, - "project_files": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "skill_discovery": { - "type": "boolean" - }, - "standing_instructions": { - "type": "boolean" - } - }, - "required": [ - "persona", - "rules", - "project_files", - "skill_discovery", - "standing_instructions" - ], - "additionalProperties": false - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "model": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - } - }, - "required": [ - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "compaction": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "threshold": { - "type": "number" - } - }, - "required": [ - "model", - "provider", - "threshold" - ], - "additionalProperties": false - }, - "mcp": { - "type": "object", - "properties": { - "servers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "servers" - ], - "additionalProperties": false - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "input_schema": true, - "output_schema": true, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "name", - "description", - "input_schema", - "output_schema", - "timeout_millis" - ], - "additionalProperties": false - } - }, - "output": true, - "children": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "instructions": { - "type": [ - "null", - "object" - ], - "properties": { - "persona": { - "type": "string" - }, - "rules": { - "type": "string" - }, - "project_files": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "skill_discovery": { - "type": "boolean" - }, - "standing_instructions": { - "type": "boolean" - } - }, - "required": [ - "persona", - "rules", - "project_files", - "skill_discovery", - "standing_instructions" - ], - "additionalProperties": false - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "model": { - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - } - }, - "required": [ - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - }, - "output": true - }, - "required": [ - "instructions", - "modules", - "capabilities", - "tools", - "model", - "budgets", - "report", - "output" - ], - "additionalProperties": false - } - }, - "surface": { - "type": "object", - "properties": { - "auto_title": { - "type": "boolean" - }, - "goal_loop": { - "type": "boolean" - } - }, - "required": [ - "auto_title", - "goal_loop" - ], - "additionalProperties": false - }, - "hooks": { - "type": [ - "null", - "object" - ], - "properties": { - "before_tool": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - }, - "before_spawn": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - }, - "turn_start": { - "type": [ - "null", - "object" - ], - "properties": { - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "optional": { - "type": "boolean" - }, - "timeout_millis": { - "type": "integer" - } - }, - "required": [ - "operations", - "optional", - "timeout_millis" - ], - "additionalProperties": false - } - }, - "required": [ - "before_tool", - "before_spawn", - "turn_start" - ], - "additionalProperties": false - } - }, - "required": [ - "id", - "instructions", - "modules", - "capabilities", - "model", - "compaction", - "mcp", - "tools", - "output", - "children", - "surface", - "hooks" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/DefinitionRegisterParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DefinitionRegisterParams", - "required": [ - "definition" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/DefinitionRegisterResult.json b/packages/protocol/schema/DefinitionRegisterResult.json deleted file mode 100644 index 7c2ada3d9..000000000 --- a/packages/protocol/schema/DefinitionRegisterResult.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "created": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/DefinitionRegisterResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "DefinitionRegisterResult", - "required": [ - "id", - "revision", - "created" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/EffortParams.json b/packages/protocol/schema/EffortParams.json deleted file mode 100644 index d95437098..000000000 --- a/packages/protocol/schema/EffortParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "effort": { - "type": "string" - }, - "persist_default": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/EffortParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EffortParams", - "required": [ - "effort", - "persist_default" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/EffortResult.json b/packages/protocol/schema/EffortResult.json deleted file mode 100644 index 46675afdb..000000000 --- a/packages/protocol/schema/EffortResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "effort": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/EffortResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EffortResult", - "required": [ - "effort" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/Empty.json b/packages/protocol/schema/Empty.json deleted file mode 100644 index d480c3767..000000000 --- a/packages/protocol/schema/Empty.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "object", - "$id": "https://whip.dev/protocol/v6/Empty", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Empty", - "additionalProperties": false -} diff --git a/packages/protocol/schema/EmptyParams.json b/packages/protocol/schema/EmptyParams.json deleted file mode 100644 index b0d759f3b..000000000 --- a/packages/protocol/schema/EmptyParams.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "object", - "$id": "https://whip.dev/protocol/v6/EmptyParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EmptyParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/EventNotification.json b/packages/protocol/schema/EventNotification.json deleted file mode 100644 index d02b74ffd..000000000 --- a/packages/protocol/schema/EventNotification.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "type": "object", - "properties": { - "event": { - "type": "object", - "properties": { - "subscription_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "payload": true - }, - "required": [ - "root_id", - "seq", - "kind" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/EventNotification", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "EventNotification", - "required": [ - "event" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ExecutorBindParams.json b/packages/protocol/schema/ExecutorBindParams.json deleted file mode 100644 index c52b67c6a..000000000 --- a/packages/protocol/schema/ExecutorBindParams.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "type": "object", - "properties": { - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "hooks": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/ExecutorBindParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecutorBindParams", - "required": [ - "definition", - "revision", - "tools" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ExecutorBindResult.json b/packages/protocol/schema/ExecutorBindResult.json deleted file mode 100644 index 6bc4dce1a..000000000 --- a/packages/protocol/schema/ExecutorBindResult.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "type": "object", - "properties": { - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "hooks": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/ExecutorBindResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecutorBindResult", - "required": [ - "generation", - "tools" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ExecutorPendingParams.json b/packages/protocol/schema/ExecutorPendingParams.json deleted file mode 100644 index eab85a3b3..000000000 --- a/packages/protocol/schema/ExecutorPendingParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/ExecutorPendingParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecutorPendingParams", - "required": [ - "definition", - "revision", - "generation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ExecutorPendingResult.json b/packages/protocol/schema/ExecutorPendingResult.json deleted file mode 100644 index 50a9d54bc..000000000 --- a/packages/protocol/schema/ExecutorPendingResult.json +++ /dev/null @@ -1,281 +0,0 @@ -{ - "type": "object", - "properties": { - "invocations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "input": true, - "deadline_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "invocation_id", - "definition", - "revision", - "generation", - "root_id", - "agent_id", - "turn_id", - "tool", - "input", - "deadline_millis" - ], - "additionalProperties": false - } - }, - "hooks": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "hook": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "arguments": true, - "spawn": { - "type": [ - "null", - "object" - ], - "properties": { - "request": { - "type": "object", - "properties": { - "prompt": { - "type": "string" - }, - "name": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "mcp_tools": true, - "browser_attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "prompt", - "name", - "definition", - "capabilities", - "tools", - "budgets", - "report", - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "resolved": { - "type": "object", - "properties": { - "browser_attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "definition": { - "type": "string" - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - } - }, - "required": [ - "definition", - "modules", - "capabilities", - "tools", - "budgets", - "report" - ], - "additionalProperties": false - } - }, - "required": [ - "request", - "resolved" - ], - "additionalProperties": false - }, - "input": { - "type": "string" - }, - "permission_mode": { - "type": "string" - }, - "deadline_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "invocation_id", - "definition", - "revision", - "generation", - "root_id", - "agent_id", - "turn_id", - "hook", - "permission_mode", - "deadline_millis" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/ExecutorPendingResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ExecutorPendingResult", - "required": [ - "invocations" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ForkParams.json b/packages/protocol/schema/ForkParams.json deleted file mode 100644 index 662598b67..000000000 --- a/packages/protocol/schema/ForkParams.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "object", - "properties": { - "expected_revision": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "title": { - "type": "string" - }, - "cut": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ForkParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ForkParams", - "required": [ - "expected_revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/GatewayStatus.json b/packages/protocol/schema/GatewayStatus.json deleted file mode 100644 index 26f262a19..000000000 --- a/packages/protocol/schema/GatewayStatus.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "state": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "error": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/GatewayStatus", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "GatewayStatus", - "required": [ - "state" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/GoalContextParams.json b/packages/protocol/schema/GoalContextParams.json deleted file mode 100644 index fb1702620..000000000 --- a/packages/protocol/schema/GoalContextParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "window": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/GoalContextParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "GoalContextParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/GoalResult.json b/packages/protocol/schema/GoalResult.json deleted file mode 100644 index 05a90e206..000000000 --- a/packages/protocol/schema/GoalResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "goal": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/GoalResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "GoalResult", - "required": [ - "goal" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HistoryPageParams.json b/packages/protocol/schema/HistoryPageParams.json deleted file mode 100644 index 5b5e5d676..000000000 --- a/packages/protocol/schema/HistoryPageParams.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "after_seq": { - "type": "integer" - }, - "before_seq": { - "type": "integer" - }, - "through_seq": { - "type": "integer" - }, - "revision": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "integer" - }, - "max_bytes": { - "type": "integer" - }, - "recent": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/HistoryPageParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HistoryPageParams", - "required": [ - "root_id", - "agent_id", - "through_seq", - "limit", - "max_bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HookInvokeParams.json b/packages/protocol/schema/HookInvokeParams.json deleted file mode 100644 index db3a8a54f..000000000 --- a/packages/protocol/schema/HookInvokeParams.json +++ /dev/null @@ -1,210 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "hook": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "arguments": true, - "spawn": { - "type": [ - "null", - "object" - ], - "properties": { - "request": { - "type": "object", - "properties": { - "prompt": { - "type": "string" - }, - "name": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "mcp_tools": true, - "browser_attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "prompt", - "name", - "definition", - "capabilities", - "tools", - "budgets", - "report", - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "resolved": { - "type": "object", - "properties": { - "browser_attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "definition": { - "type": "string" - }, - "modules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - } - }, - "required": [ - "definition", - "modules", - "capabilities", - "tools", - "budgets", - "report" - ], - "additionalProperties": false - } - }, - "required": [ - "request", - "resolved" - ], - "additionalProperties": false - }, - "input": { - "type": "string" - }, - "permission_mode": { - "type": "string" - }, - "deadline_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/HookInvokeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HookInvokeParams", - "required": [ - "invocation_id", - "definition", - "revision", - "generation", - "root_id", - "agent_id", - "turn_id", - "hook", - "permission_mode", - "deadline_millis" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HookResultParams.json b/packages/protocol/schema/HookResultParams.json deleted file mode 100644 index d9e5513f1..000000000 --- a/packages/protocol/schema/HookResultParams.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "decision": { - "type": "string" - }, - "reason": { - "type": "string" - }, - "arguments": true, - "spawn": { - "type": [ - "null", - "object" - ], - "properties": { - "prompt": { - "type": "string" - }, - "name": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "tools": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "budgets": { - "type": "object", - "additionalProperties": { - "type": "integer" - } - }, - "report": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "mcp_tools": true, - "browser_attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "prompt", - "name", - "definition", - "capabilities", - "tools", - "budgets", - "report", - "model", - "provider", - "effort" - ], - "additionalProperties": false - }, - "context": { - "type": "string" - }, - "error": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/HookResultParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HookResultParams", - "required": [ - "invocation_id", - "generation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostAttentionParams.json b/packages/protocol/schema/HostAttentionParams.json deleted file mode 100644 index 64a95d079..000000000 --- a/packages/protocol/schema/HostAttentionParams.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "object", - "properties": { - "after_id": { - "type": "string" - }, - "limit": { - "type": "integer" - }, - "max_bytes": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/HostAttentionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostAttentionParams", - "required": [ - "limit", - "max_bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostAttentionResult.json b/packages/protocol/schema/HostAttentionResult.json deleted file mode 100644 index 2933013a8..000000000 --- a/packages/protocol/schema/HostAttentionResult.json +++ /dev/null @@ -1,411 +0,0 @@ -{ - "type": "object", - "properties": { - "items": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "active_agents": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_permissions": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "questions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "turn_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "sender_agent_id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "inbox_kind": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "message_id": { - "type": "string" - }, - "phase": { - "type": "string" - }, - "status": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "schedule_id": { - "type": "integer" - }, - "slot": { - "type": "string" - }, - "error": { - "type": "string" - }, - "model_call": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "logical_id": { - "type": "string" - }, - "number": { - "type": "integer" - }, - "purpose": { - "type": "string" - }, - "usage_source": { - "type": "string" - }, - "cost_source": { - "type": "string" - }, - "tokens": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "elapsed_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "exhausted": { - "type": "boolean" - } - }, - "required": [ - "id", - "logical_id", - "number", - "purpose", - "usage_source", - "cost_source", - "tokens", - "cost_micros", - "elapsed_millis", - "exhausted" - ], - "additionalProperties": false - }, - "acknowledged_inbox": { - "type": "array", - "items": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "subscription_id": { - "type": "string" - }, - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "expected_version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "not_restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "required": [ - "name", - "reason" - ], - "additionalProperties": false - } - }, - "attempt": { - "type": "string" - }, - "budget_kind": { - "type": "string" - }, - "amount": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "capability_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "permission_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - }, - "rule_source": { - "type": "string" - }, - "question_id": { - "type": "string" - }, - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - }, - "questions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - } - }, - "required": [ - "question" - ], - "additionalProperties": false - } - }, - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - }, - "answers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - }, - "additionalProperties": false - } - }, - "truncated": { - "type": "boolean" - } - }, - "required": [ - "root_id", - "title", - "active_agents", - "pending_permissions", - "questions", - "truncated" - ], - "additionalProperties": false - } - }, - "next_after_id": { - "type": "string" - }, - "has_more": { - "type": "boolean" - }, - "truncated": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/HostAttentionResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostAttentionResult", - "required": [ - "items", - "has_more", - "truncated" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostDirectoryParams.json b/packages/protocol/schema/HostDirectoryParams.json deleted file mode 100644 index 392926cf6..000000000 --- a/packages/protocol/schema/HostDirectoryParams.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "after": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "show_hidden": { - "type": "boolean" - }, - "limit": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/HostDirectoryParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostDirectoryParams", - "required": [ - "limit" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostDirectoryPickParams.json b/packages/protocol/schema/HostDirectoryPickParams.json deleted file mode 100644 index fb2472a2e..000000000 --- a/packages/protocol/schema/HostDirectoryPickParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "start": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/HostDirectoryPickParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostDirectoryPickParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostDirectoryPickResult.json b/packages/protocol/schema/HostDirectoryPickResult.json deleted file mode 100644 index 7d5a339c9..000000000 --- a/packages/protocol/schema/HostDirectoryPickResult.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "cancelled": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/HostDirectoryPickResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostDirectoryPickResult", - "required": [ - "cancelled" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostDirectoryResult.json b/packages/protocol/schema/HostDirectoryResult.json deleted file mode 100644 index 605a806fe..000000000 --- a/packages/protocol/schema/HostDirectoryResult.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "object", - "properties": { - "path": { - "type": "string" - }, - "parent": { - "type": "string" - }, - "entries": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "path": { - "type": "string" - } - }, - "required": [ - "name", - "path" - ], - "additionalProperties": false - } - }, - "next_after": { - "type": "string" - }, - "has_more": { - "type": "boolean" - }, - "truncated": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/HostDirectoryResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostDirectoryResult", - "required": [ - "path", - "parent", - "entries", - "has_more", - "truncated" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/HostSkillCompletionParams.json b/packages/protocol/schema/HostSkillCompletionParams.json deleted file mode 100644 index 42c6e9388..000000000 --- a/packages/protocol/schema/HostSkillCompletionParams.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$id": "https://whip.dev/protocol/v6/HostSkillCompletionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostSkillCompletionParams", - "allOf": [ - { - "type": "object", - "properties": { - "scope": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "permission_mode": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "limit": { - "type": "integer" - } - }, - "required": [ - "prefix", - "limit" - ], - "additionalProperties": false - }, - { - "oneOf": [ - { - "type": "object", - "properties": { - "cwd": { - "type": "string", - "pattern": "^[\\s\\S]+$" - }, - "scope": { - "type": "string", - "enum": [ - "" - ] - } - }, - "required": [ - "cwd" - ] - }, - { - "type": "object", - "properties": { - "cwd": { - "type": "string", - "enum": [ - "" - ] - }, - "scope": { - "type": "string", - "enum": [ - "global" - ] - } - }, - "required": [ - "scope" - ] - } - ] - } - ] -} diff --git a/packages/protocol/schema/HostThemeResolveParams.json b/packages/protocol/schema/HostThemeResolveParams.json deleted file mode 100644 index 60411d9a2..000000000 --- a/packages/protocol/schema/HostThemeResolveParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "json": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/HostThemeResolveParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "HostThemeResolveParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/IDParams.json b/packages/protocol/schema/IDParams.json deleted file mode 100644 index 29188f9d0..000000000 --- a/packages/protocol/schema/IDParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/IDParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "IDParams", - "required": [ - "id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/InboxControlResult.json b/packages/protocol/schema/InboxControlResult.json deleted file mode 100644 index d5804b687..000000000 --- a/packages/protocol/schema/InboxControlResult.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "agent_id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/InboxControlResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InboxControlResult", - "required": [ - "agent_id", - "inbox_seq", - "status" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/InboxRemoveParams.json b/packages/protocol/schema/InboxRemoveParams.json deleted file mode 100644 index 810aa9a13..000000000 --- a/packages/protocol/schema/InboxRemoveParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/InboxRemoveParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InboxRemoveParams", - "required": [ - "id", - "inbox_seq" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/InboxSteerParams.json b/packages/protocol/schema/InboxSteerParams.json deleted file mode 100644 index 0174b054f..000000000 --- a/packages/protocol/schema/InboxSteerParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "turn_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/InboxSteerParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InboxSteerParams", - "required": [ - "id", - "inbox_seq", - "turn_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/InitializeParams.json b/packages/protocol/schema/InitializeParams.json deleted file mode 100644 index 15172617b..000000000 --- a/packages/protocol/schema/InitializeParams.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "type": "object", - "properties": { - "protocol_major": { - "type": "integer" - }, - "build_id": { - "type": "string" - }, - "client_kind": { - "type": "string" - }, - "client_id": { - "type": "string" - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/InitializeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InitializeParams", - "required": [ - "protocol_major", - "build_id", - "client_kind", - "client_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/InitializeResult.json b/packages/protocol/schema/InitializeResult.json deleted file mode 100644 index 72e43f477..000000000 --- a/packages/protocol/schema/InitializeResult.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "type": "object", - "properties": { - "execution_engines": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "bridge_sha256": { - "type": "string" - }, - "build": { - "type": "string" - }, - "abi": { - "type": "string" - }, - "profile": { - "type": "string" - }, - "fidelity": { - "type": "string" - }, - "guide_sha256": { - "type": "string" - }, - "features": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "default_limits": { - "type": "object", - "additionalProperties": { - "type": "integer", - "minimum": 0 - } - }, - "id": { - "type": "string" - }, - "language": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "required": [ - "id", - "language", - "label" - ], - "additionalProperties": false - } - }, - "default_execution_engine": { - "type": "string" - }, - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "surface": { - "type": "string" - }, - "execution": { - "type": "string" - }, - "permission": { - "type": "string" - }, - "sensitive": { - "type": "boolean" - } - }, - "required": [ - "name", - "surface", - "execution", - "permission" - ], - "additionalProperties": false - } - }, - "limits": { - "type": "object", - "properties": { - "frame_bytes": { - "type": "integer" - }, - "connections": { - "type": "integer" - }, - "in_flight_requests": { - "type": "integer" - }, - "outbound_messages": { - "type": "integer" - }, - "outbound_bytes": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_subscriptions": { - "type": "integer" - }, - "content_chunk_bytes": { - "type": "integer" - }, - "upload_bytes": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "frame_bytes", - "connections", - "in_flight_requests", - "outbound_messages", - "outbound_bytes", - "root_subscriptions", - "content_chunk_bytes", - "upload_bytes" - ], - "additionalProperties": false - }, - "negotiated_capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "protocol_minor": { - "type": "integer" - }, - "runtime_id": { - "type": "string" - }, - "connection_id": { - "type": "string" - }, - "host_platform": { - "type": "string" - }, - "host_architecture": { - "type": "string" - }, - "network_endpoint": { - "type": "string" - }, - "protocol_major": { - "type": "integer" - }, - "build_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pid": { - "type": "integer" - }, - "started_at": { - "type": "string" - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/InitializeResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "InitializeResult", - "required": [ - "execution_engines", - "default_execution_engine", - "operations", - "limits", - "negotiated_capabilities", - "protocol_minor", - "runtime_id", - "connection_id", - "host_platform", - "host_architecture", - "protocol_major", - "build_id", - "generation", - "capabilities" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/LSPListResult.json b/packages/protocol/schema/LSPListResult.json deleted file mode 100644 index 38135ce65..000000000 --- a/packages/protocol/schema/LSPListResult.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "root": { - "type": "string" - }, - "state": { - "type": "string" - }, - "error": { - "type": "string" - } - }, - "required": [ - "name", - "state" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/LSPListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "LSPListResult" -} diff --git a/packages/protocol/schema/LifecycleEvent.json b/packages/protocol/schema/LifecycleEvent.json deleted file mode 100644 index 15dead23a..000000000 --- a/packages/protocol/schema/LifecycleEvent.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "type": "object", - "properties": { - "turn_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "sender_agent_id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "inbox_kind": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "message_id": { - "type": "string" - }, - "phase": { - "type": "string" - }, - "status": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "schedule_id": { - "type": "integer" - }, - "slot": { - "type": "string" - }, - "error": { - "type": "string" - }, - "model_call": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "logical_id": { - "type": "string" - }, - "number": { - "type": "integer" - }, - "purpose": { - "type": "string" - }, - "usage_source": { - "type": "string" - }, - "cost_source": { - "type": "string" - }, - "tokens": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "elapsed_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "exhausted": { - "type": "boolean" - } - }, - "required": [ - "id", - "logical_id", - "number", - "purpose", - "usage_source", - "cost_source", - "tokens", - "cost_micros", - "elapsed_millis", - "exhausted" - ], - "additionalProperties": false - }, - "acknowledged_inbox": { - "type": "array", - "items": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "subscription_id": { - "type": "string" - }, - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "expected_version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "not_restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "required": [ - "name", - "reason" - ], - "additionalProperties": false - } - }, - "attempt": { - "type": "string" - }, - "budget_kind": { - "type": "string" - }, - "amount": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "capability_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "permission_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - }, - "rule_source": { - "type": "string" - }, - "question_id": { - "type": "string" - }, - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - }, - "questions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - } - }, - "required": [ - "question" - ], - "additionalProperties": false - } - }, - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - }, - "answers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/LifecycleEvent", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "LifecycleEvent", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ListParams.json b/packages/protocol/schema/ListParams.json deleted file mode 100644 index 86f7f2f64..000000000 --- a/packages/protocol/schema/ListParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "limit": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ListParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ListParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPAttachParams.json b/packages/protocol/schema/MCPAttachParams.json deleted file mode 100644 index b73978b94..000000000 --- a/packages/protocol/schema/MCPAttachParams.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "type": "object", - "properties": { - "servers": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "command": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "env": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "cwd": { - "type": "string" - }, - "url": { - "type": "string" - }, - "headers": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "enabled": { - "type": [ - "null", - "boolean" - ] - }, - "note": { - "type": "string" - }, - "startup_timeout": { - "type": "integer" - }, - "tool_timeout": { - "type": "integer" - }, - "source": { - "type": "string" - }, - "origin": { - "type": "string" - } - }, - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPAttachParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPAttachParams", - "required": [ - "servers" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPBrandIconsParams.json b/packages/protocol/schema/MCPBrandIconsParams.json deleted file mode 100644 index 211a31787..000000000 --- a/packages/protocol/schema/MCPBrandIconsParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "keys": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPBrandIconsParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPBrandIconsParams", - "required": [ - "keys" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPBrandIconsResult.json b/packages/protocol/schema/MCPBrandIconsResult.json deleted file mode 100644 index e9ef8332a..000000000 --- a/packages/protocol/schema/MCPBrandIconsResult.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "icons": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPBrandIconsResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPBrandIconsResult", - "required": [ - "icons" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportApplyParams.json b/packages/protocol/schema/MCPImportApplyParams.json deleted file mode 100644 index d2c19530b..000000000 --- a/packages/protocol/schema/MCPImportApplyParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "cwd": { - "type": "string" - }, - "names": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportApplyParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportApplyParams", - "required": [ - "names" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportApplyResult.json b/packages/protocol/schema/MCPImportApplyResult.json deleted file mode 100644 index 3f2609b1a..000000000 --- a/packages/protocol/schema/MCPImportApplyResult.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "object", - "properties": { - "imported": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "skipped": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportApplyResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportApplyResult", - "required": [ - "imported" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportCandidatesParams.json b/packages/protocol/schema/MCPImportCandidatesParams.json deleted file mode 100644 index 0d7a766ae..000000000 --- a/packages/protocol/schema/MCPImportCandidatesParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "cwd": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportCandidatesParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportCandidatesParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportCandidatesResult.json b/packages/protocol/schema/MCPImportCandidatesResult.json deleted file mode 100644 index 8be02e555..000000000 --- a/packages/protocol/schema/MCPImportCandidatesResult.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "type": "object", - "properties": { - "candidates": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "source": { - "type": "string" - }, - "state": { - "type": "string" - }, - "note": { - "type": "string" - }, - "brand_hint": { - "type": "string" - }, - "brand_key": { - "type": "string" - } - }, - "required": [ - "name", - "source", - "state" - ], - "additionalProperties": false - } - }, - "offered": { - "type": "boolean" - }, - "config_path": { - "type": "string" - }, - "errors": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportCandidatesResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportCandidatesResult", - "required": [ - "candidates", - "offered", - "config_path" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportParams.json b/packages/protocol/schema/MCPImportParams.json deleted file mode 100644 index eabdd483b..000000000 --- a/packages/protocol/schema/MCPImportParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "source": { - "type": "string" - }, - "enabled": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportParams", - "required": [ - "source", - "enabled" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPImportStatusResult.json b/packages/protocol/schema/MCPImportStatusResult.json deleted file mode 100644 index 271c15e65..000000000 --- a/packages/protocol/schema/MCPImportStatusResult.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "object", - "properties": { - "claude": { - "type": "boolean" - }, - "codex": { - "type": "boolean" - }, - "project": { - "type": "boolean" - }, - "opencode": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/MCPImportStatusResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPImportStatusResult", - "required": [ - "claude", - "codex", - "project", - "opencode" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPListResult.json b/packages/protocol/schema/MCPListResult.json deleted file mode 100644 index 6b7cd6d00..000000000 --- a/packages/protocol/schema/MCPListResult.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "note": { - "type": "string" - }, - "error": { - "type": "string" - }, - "tools": { - "type": "integer" - }, - "source": { - "type": "string" - } - }, - "required": [ - "name", - "status" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/MCPListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPListResult" -} diff --git a/packages/protocol/schema/MCPRefreshResult.json b/packages/protocol/schema/MCPRefreshResult.json deleted file mode 100644 index d36d23001..000000000 --- a/packages/protocol/schema/MCPRefreshResult.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "type": "object", - "properties": { - "added": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "existing": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "changed": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "servers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "note": { - "type": "string" - }, - "error": { - "type": "string" - }, - "tools": { - "type": "integer" - }, - "source": { - "type": "string" - } - }, - "required": [ - "name", - "status" - ], - "additionalProperties": false - } - }, - "blocked": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "note": { - "type": "string" - }, - "error": { - "type": "string" - }, - "tools": { - "type": "integer" - }, - "source": { - "type": "string" - } - }, - "required": [ - "name", - "status" - ], - "additionalProperties": false - } - }, - "source_errors": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "note": { - "type": "string" - }, - "error": { - "type": "string" - }, - "tools": { - "type": "integer" - }, - "source": { - "type": "string" - } - }, - "required": [ - "name", - "status" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/MCPRefreshResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPRefreshResult", - "required": [ - "added", - "existing", - "changed", - "servers", - "blocked", - "source_errors" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MCPServerParams.json b/packages/protocol/schema/MCPServerParams.json deleted file mode 100644 index 439d09294..000000000 --- a/packages/protocol/schema/MCPServerParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "name": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/MCPServerParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MCPServerParams", - "required": [ - "name" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MailboxInspection.json b/packages/protocol/schema/MailboxInspection.json deleted file mode 100644 index 07f857b2c..000000000 --- a/packages/protocol/schema/MailboxInspection.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "sender": { - "type": "string" - }, - "recipient": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "subject": { - "type": "string" - }, - "excerpt": { - "type": "string" - }, - "body": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "evidence_handle": { - "type": "string" - }, - "status": { - "type": "string" - }, - "available_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "delivered_at": { - "type": "string" - }, - "delivered_turn_id": { - "type": "string" - }, - "done_at": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/MailboxInspection", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MailboxInspection", - "required": [ - "id", - "revision", - "sender", - "recipient", - "kind", - "delivery", - "subject", - "excerpt", - "body", - "status", - "available_at", - "created_at", - "delivered_at", - "done_at" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MailboxPage.json b/packages/protocol/schema/MailboxPage.json deleted file mode 100644 index 2143f7150..000000000 --- a/packages/protocol/schema/MailboxPage.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "items": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "sender": { - "type": "string" - }, - "recipient": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "subject": { - "type": "string" - }, - "excerpt": { - "type": "string" - }, - "body": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "evidence_handle": { - "type": "string" - }, - "status": { - "type": "string" - }, - "available_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "delivered_at": { - "type": "string" - }, - "delivered_turn_id": { - "type": "string" - }, - "done_at": { - "type": "string" - } - }, - "required": [ - "id", - "revision", - "sender", - "recipient", - "kind", - "delivery", - "subject", - "excerpt", - "body", - "status", - "available_at", - "created_at", - "delivered_at", - "done_at" - ], - "additionalProperties": false - } - }, - "next_cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "status", - "revision", - "offset" - ], - "additionalProperties": false - }, - "has_more": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/MailboxPage", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MailboxPage", - "required": [ - "revision", - "items", - "has_more" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MailboxPageParams.json b/packages/protocol/schema/MailboxPageParams.json deleted file mode 100644 index 2262e6afc..000000000 --- a/packages/protocol/schema/MailboxPageParams.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "status", - "revision", - "offset" - ], - "additionalProperties": false - }, - "limit": { - "type": "integer" - }, - "max_bytes": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/MailboxPageParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MailboxPageParams", - "required": [ - "root_id", - "agent_id", - "limit", - "max_bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/MailboxReadParams.json b/packages/protocol/schema/MailboxReadParams.json deleted file mode 100644 index 2e1784742..000000000 --- a/packages/protocol/schema/MailboxReadParams.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/MailboxReadParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "MailboxReadParams", - "required": [ - "root_id", - "agent_id", - "id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ModelParams.json b/packages/protocol/schema/ModelParams.json deleted file mode 100644 index c924e1d68..000000000 --- a/packages/protocol/schema/ModelParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "effort": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "persist_default": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ModelParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ModelParams", - "required": [ - "model", - "persist_default" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ModelResult.json b/packages/protocol/schema/ModelResult.json deleted file mode 100644 index b3077a9bd..000000000 --- a/packages/protocol/schema/ModelResult.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "object", - "properties": { - "reload_pending": { - "type": "boolean" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ModelResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ModelResult", - "required": [ - "model", - "provider" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PathParams.json b/packages/protocol/schema/PathParams.json deleted file mode 100644 index ce41ae5e6..000000000 --- a/packages/protocol/schema/PathParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "path": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/PathParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PathParams", - "required": [ - "path" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PathResult.json b/packages/protocol/schema/PathResult.json deleted file mode 100644 index 43d197c37..000000000 --- a/packages/protocol/schema/PathResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "path": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/PathResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PathResult", - "required": [ - "path" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PermissionConfigureParams.json b/packages/protocol/schema/PermissionConfigureParams.json deleted file mode 100644 index 83f3ea243..000000000 --- a/packages/protocol/schema/PermissionConfigureParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "external_permissions": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/PermissionConfigureParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PermissionConfigureParams", - "required": [ - "external_permissions" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PermissionDecision.json b/packages/protocol/schema/PermissionDecision.json deleted file mode 100644 index 984a74a79..000000000 --- a/packages/protocol/schema/PermissionDecision.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "permission_id": { - "type": "string" - }, - "allow": { - "type": "boolean" - }, - "reason": { - "type": "string" - }, - "remember": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/PermissionDecision", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PermissionDecision", - "required": [ - "command_id", - "root_id", - "permission_id", - "allow" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PermissionDecisionParams.json b/packages/protocol/schema/PermissionDecisionParams.json deleted file mode 100644 index 29c059272..000000000 --- a/packages/protocol/schema/PermissionDecisionParams.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "type": "object", - "properties": { - "decision": { - "type": "object", - "properties": { - "command_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "permission_id": { - "type": "string" - }, - "allow": { - "type": "boolean" - }, - "reason": { - "type": "string" - }, - "remember": { - "type": "string" - } - }, - "required": [ - "command_id", - "root_id", - "permission_id", - "allow" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/PermissionDecisionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PermissionDecisionParams", - "required": [ - "decision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PermissionDecisionResult.json b/packages/protocol/schema/PermissionDecisionResult.json deleted file mode 100644 index 4d76b9aaa..000000000 --- a/packages/protocol/schema/PermissionDecisionResult.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "operation_id": { - "type": "string" - }, - "lease_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/PermissionDecisionResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PermissionDecisionResult", - "required": [ - "operation_id", - "lease_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PermissionRulesResult.json b/packages/protocol/schema/PermissionRulesResult.json deleted file mode 100644 index ab1c9c0fe..000000000 --- a/packages/protocol/schema/PermissionRulesResult.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "type": "object", - "properties": { - "rules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "rule": { - "type": "string" - }, - "principal_id": { - "type": "string" - }, - "created_at": { - "type": "string" - } - }, - "required": [ - "id", - "root_id", - "operation", - "rule", - "principal_id", - "created_at" - ], - "additionalProperties": false - } - }, - "global": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/PermissionRulesResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PermissionRulesResult", - "required": [ - "rules", - "global" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/PingResult.json b/packages/protocol/schema/PingResult.json deleted file mode 100644 index fef748eed..000000000 --- a/packages/protocol/schema/PingResult.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "build_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/PingResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "PingResult", - "required": [ - "generation", - "build_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderCatalogParams.json b/packages/protocol/schema/ProviderCatalogParams.json deleted file mode 100644 index 424f5146f..000000000 --- a/packages/protocol/schema/ProviderCatalogParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "refresh": { - "type": "boolean" - }, - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderCatalogParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderCatalogParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderCatalogsResult.json b/packages/protocol/schema/ProviderCatalogsResult.json deleted file mode 100644 index c0c137c59..000000000 --- a/packages/protocol/schema/ProviderCatalogsResult.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "type": "object", - "properties": { - "models": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "id": { - "type": "string" - }, - "providers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "context": { - "type": "integer" - }, - "vision": { - "type": "boolean" - } - }, - "required": [ - "providers" - ], - "additionalProperties": false - } - }, - "providers": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "base_url": { - "type": "string" - }, - "available": { - "type": [ - "null", - "boolean" - ] - } - }, - "required": [ - "base_url" - ], - "additionalProperties": false - } - }, - "catalogs": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "fetched_at": { - "type": "string" - }, - "base_url": { - "type": "string" - }, - "models": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "pricing": { - "type": [ - "null", - "object" - ], - "properties": { - "prompt": { - "type": "string" - }, - "completion": { - "type": "string" - }, - "input_cache_read": { - "type": "string" - } - }, - "required": [ - "prompt", - "completion" - ], - "additionalProperties": false - }, - "pricing_known": { - "type": "boolean" - }, - "cache_read_price_known": { - "type": "boolean" - }, - "id": { - "type": "string" - }, - "context_length": { - "type": "integer" - }, - "max_completion_tokens": { - "type": "integer" - }, - "reasoning_efforts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "in_price": { - "type": "number" - }, - "out_price": { - "type": "number" - }, - "cache_read_price": { - "type": "number" - }, - "input_modalities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "id" - ], - "additionalProperties": false - } - } - }, - "required": [ - "fetched_at", - "base_url", - "models" - ], - "additionalProperties": false - } - }, - "errors": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderCatalogsResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderCatalogsResult", - "required": [ - "models", - "providers", - "catalogs" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderConfiguration.json b/packages/protocol/schema/ProviderConfiguration.json deleted file mode 100644 index eb9eb4a48..000000000 --- a/packages/protocol/schema/ProviderConfiguration.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "definition": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "base_url": { - "type": "string" - }, - "api": { - "type": "string" - } - }, - "required": [ - "name", - "base_url", - "api" - ], - "additionalProperties": false - }, - "custom": { - "type": "boolean" - }, - "credential": { - "type": "object", - "properties": { - "mode": { - "type": "string" - }, - "configured": { - "type": "boolean" - }, - "environment_variable": { - "type": "string" - }, - "credential_path": { - "type": "string" - }, - "available": { - "type": [ - "null", - "boolean" - ] - } - }, - "required": [ - "mode", - "configured" - ], - "additionalProperties": false - }, - "models": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "alias": { - "type": "string" - }, - "id": { - "type": "string" - }, - "context": { - "type": "integer" - }, - "max_output": { - "type": "integer" - } - }, - "required": [ - "alias", - "id" - ], - "additionalProperties": false - } - }, - "removal_blockers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "discovery": { - "type": [ - "null", - "object" - ], - "properties": { - "status": { - "type": "string" - }, - "message": { - "type": "string" - }, - "model_count": { - "type": "integer" - } - }, - "required": [ - "status" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderConfiguration", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderConfiguration", - "required": [ - "revision", - "provider", - "definition", - "custom", - "credential", - "models", - "removal_blockers" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderCreateParams.json b/packages/protocol/schema/ProviderCreateParams.json deleted file mode 100644 index 099aa76a2..000000000 --- a/packages/protocol/schema/ProviderCreateParams.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "definition": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "base_url": { - "type": "string" - }, - "api": { - "type": "string" - } - }, - "required": [ - "name", - "base_url", - "api" - ], - "additionalProperties": false - }, - "credential": { - "type": "object", - "properties": { - "mode": { - "type": "string" - }, - "key": { - "type": "string" - }, - "environment_variable": { - "type": "string" - } - }, - "required": [ - "mode" - ], - "additionalProperties": false - }, - "manual_model": { - "type": [ - "null", - "object" - ], - "properties": { - "alias": { - "type": "string" - }, - "id": { - "type": "string" - }, - "context": { - "type": "integer" - }, - "max_output": { - "type": "integer" - } - }, - "required": [ - "alias", - "id" - ], - "additionalProperties": false - }, - "allow_unverified": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderCreateParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderCreateParams", - "required": [ - "revision", - "provider", - "definition", - "credential" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderDisconnectParams.json b/packages/protocol/schema/ProviderDisconnectParams.json deleted file mode 100644 index d0d400d7f..000000000 --- a/packages/protocol/schema/ProviderDisconnectParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "revision": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderDisconnectParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderDisconnectParams", - "required": [ - "provider", - "revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderKeySetup.json b/packages/protocol/schema/ProviderKeySetup.json deleted file mode 100644 index dd28725a0..000000000 --- a/packages/protocol/schema/ProviderKeySetup.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "key": { - "type": "string" - }, - "environment": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderKeySetup", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderKeySetup", - "required": [ - "revision", - "provider", - "environment" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderList.json b/packages/protocol/schema/ProviderList.json deleted file mode 100644 index 2a91babb7..000000000 --- a/packages/protocol/schema/ProviderList.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "discovery_error": { - "type": "string" - }, - "default_provider": { - "type": "string" - }, - "providers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "custom": { - "type": "boolean" - }, - "methods": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "status": { - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "configured": { - "type": "boolean" - }, - "key_source": { - "type": "string" - }, - "available": { - "type": [ - "null", - "boolean" - ] - }, - "disabled": { - "type": "boolean" - }, - "environment_variable": { - "type": "string" - }, - "credential_path": { - "type": "string" - }, - "auth_method": { - "type": "string" - }, - "auth_state": { - "type": "string" - }, - "account_id": { - "type": "string" - }, - "plan": { - "type": "string" - }, - "email": { - "type": "string" - }, - "team_name": { - "type": "string" - }, - "project_id": { - "type": "string" - }, - "project_name": { - "type": "string" - }, - "machine_key_name": { - "type": "string" - }, - "warnings": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "provider", - "configured", - "key_source", - "warnings" - ], - "additionalProperties": false - }, - "recommended": { - "type": "boolean" - }, - "suggested_model": { - "type": "string" - }, - "category": { - "type": "string" - }, - "family": { - "type": "string" - }, - "key_url": { - "type": "string" - } - }, - "required": [ - "id", - "name", - "custom", - "methods", - "status" - ], - "additionalProperties": false - } - }, - "selection": { - "type": [ - "null", - "object" - ], - "properties": { - "ready": { - "type": "boolean" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "required": [ - "ready", - "model", - "provider", - "reason" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderList", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderList", - "required": [ - "revision", - "providers" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderListParams.json b/packages/protocol/schema/ProviderListParams.json deleted file mode 100644 index e7e96771e..000000000 --- a/packages/protocol/schema/ProviderListParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "model": { - "type": "string" - }, - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderListParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderListParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginBeginParams.json b/packages/protocol/schema/ProviderLoginBeginParams.json deleted file mode 100644 index f7ac365f7..000000000 --- a/packages/protocol/schema/ProviderLoginBeginParams.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "object", - "properties": { - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginBeginParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginBeginParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginCreateParams.json b/packages/protocol/schema/ProviderLoginCreateParams.json deleted file mode 100644 index 43ee84e63..000000000 --- a/packages/protocol/schema/ProviderLoginCreateParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "flow_id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginCreateParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginCreateParams", - "required": [ - "flow_id", - "name" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginList.json b/packages/protocol/schema/ProviderLoginList.json deleted file mode 100644 index df3c5e8dc..000000000 --- a/packages/protocol/schema/ProviderLoginList.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "type": "object", - "properties": { - "flows": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "flow_id": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "state": { - "type": "string" - }, - "verification_url": { - "type": "string" - }, - "user_code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "teams": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "additionalProperties": false - } - }, - "projects": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "additionalProperties": false - } - }, - "team_id": { - "type": "string" - }, - "project_id": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "error": { - "type": "string" - } - }, - "required": [ - "flow_id", - "state", - "teams", - "projects", - "expires_at" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginList", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginList", - "required": [ - "flows" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginParams.json b/packages/protocol/schema/ProviderLoginParams.json deleted file mode 100644 index 8e71ea643..000000000 --- a/packages/protocol/schema/ProviderLoginParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "flow_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginParams", - "required": [ - "flow_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginProjectParams.json b/packages/protocol/schema/ProviderLoginProjectParams.json deleted file mode 100644 index 0edfe6c73..000000000 --- a/packages/protocol/schema/ProviderLoginProjectParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "flow_id": { - "type": "string" - }, - "project_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginProjectParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginProjectParams", - "required": [ - "flow_id", - "project_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginStatus.json b/packages/protocol/schema/ProviderLoginStatus.json deleted file mode 100644 index 325c06724..000000000 --- a/packages/protocol/schema/ProviderLoginStatus.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "type": "object", - "properties": { - "flow_id": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "state": { - "type": "string" - }, - "verification_url": { - "type": "string" - }, - "user_code": { - "type": "string" - }, - "email": { - "type": "string" - }, - "teams": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "additionalProperties": false - } - }, - "projects": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - }, - "required": [ - "id", - "name" - ], - "additionalProperties": false - } - }, - "team_id": { - "type": "string" - }, - "project_id": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "error": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginStatus", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginStatus", - "required": [ - "flow_id", - "state", - "teams", - "projects", - "expires_at" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderLoginTeamParams.json b/packages/protocol/schema/ProviderLoginTeamParams.json deleted file mode 100644 index fe4a60587..000000000 --- a/packages/protocol/schema/ProviderLoginTeamParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "flow_id": { - "type": "string" - }, - "team_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderLoginTeamParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderLoginTeamParams", - "required": [ - "flow_id", - "team_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderNameParams.json b/packages/protocol/schema/ProviderNameParams.json deleted file mode 100644 index 2e5141a79..000000000 --- a/packages/protocol/schema/ProviderNameParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderNameParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderNameParams", - "required": [ - "provider" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderRemoveParams.json b/packages/protocol/schema/ProviderRemoveParams.json deleted file mode 100644 index e7ca61cbe..000000000 --- a/packages/protocol/schema/ProviderRemoveParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "provider": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderRemoveParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderRemoveParams", - "required": [ - "revision", - "provider" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderRemoveResult.json b/packages/protocol/schema/ProviderRemoveResult.json deleted file mode 100644 index 256499be4..000000000 --- a/packages/protocol/schema/ProviderRemoveResult.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "warning": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderRemoveResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderRemoveResult", - "required": [ - "revision" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderStatus.json b/packages/protocol/schema/ProviderStatus.json deleted file mode 100644 index d25c3a7a9..000000000 --- a/packages/protocol/schema/ProviderStatus.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "configured": { - "type": "boolean" - }, - "key_source": { - "type": "string" - }, - "available": { - "type": [ - "null", - "boolean" - ] - }, - "disabled": { - "type": "boolean" - }, - "environment_variable": { - "type": "string" - }, - "credential_path": { - "type": "string" - }, - "auth_method": { - "type": "string" - }, - "auth_state": { - "type": "string" - }, - "account_id": { - "type": "string" - }, - "plan": { - "type": "string" - }, - "email": { - "type": "string" - }, - "team_name": { - "type": "string" - }, - "project_id": { - "type": "string" - }, - "project_name": { - "type": "string" - }, - "machine_key_name": { - "type": "string" - }, - "warnings": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderStatus", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderStatus", - "required": [ - "provider", - "configured", - "key_source", - "warnings" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderUpdateParams.json b/packages/protocol/schema/ProviderUpdateParams.json deleted file mode 100644 index 64949ede0..000000000 --- a/packages/protocol/schema/ProviderUpdateParams.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "name": { - "type": [ - "null", - "string" - ] - }, - "base_url": { - "type": [ - "null", - "string" - ] - }, - "credential": { - "type": [ - "null", - "object" - ], - "properties": { - "mode": { - "type": "string" - }, - "key": { - "type": "string" - }, - "environment_variable": { - "type": "string" - } - }, - "required": [ - "mode" - ], - "additionalProperties": false - }, - "manual_model": { - "type": [ - "null", - "object" - ], - "properties": { - "alias": { - "type": "string" - }, - "id": { - "type": "string" - }, - "context": { - "type": "integer" - }, - "max_output": { - "type": "integer" - } - }, - "required": [ - "alias", - "id" - ], - "additionalProperties": false - }, - "allow_unverified": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderUpdateParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderUpdateParams", - "required": [ - "revision", - "provider" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderValidateParams.json b/packages/protocol/schema/ProviderValidateParams.json deleted file mode 100644 index 20aefcfd5..000000000 --- a/packages/protocol/schema/ProviderValidateParams.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "base_url": { - "type": "string" - }, - "key": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderValidateParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderValidateParams", - "required": [ - "name", - "base_url", - "key" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ProviderValidateResult.json b/packages/protocol/schema/ProviderValidateResult.json deleted file mode 100644 index 3df451453..000000000 --- a/packages/protocol/schema/ProviderValidateResult.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "type": "object", - "properties": { - "models": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "context_length": { - "type": "integer" - }, - "max_completion_tokens": { - "type": "integer" - }, - "reasoning_efforts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "pricing": { - "type": [ - "null", - "object" - ], - "properties": { - "prompt": { - "type": "string" - }, - "completion": { - "type": "string" - }, - "input_cache_read": { - "type": "string" - } - }, - "required": [ - "prompt", - "completion" - ], - "additionalProperties": false - }, - "input_modalities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "output_modalities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "supports_tools": { - "type": [ - "null", - "boolean" - ] - }, - "type": { - "type": "string" - } - }, - "required": [ - "id" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/ProviderValidateResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ProviderValidateResult", - "required": [ - "models" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/QueryParams.json b/packages/protocol/schema/QueryParams.json deleted file mode 100644 index 4f9619624..000000000 --- a/packages/protocol/schema/QueryParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "payload": true - }, - "$id": "https://whip.dev/protocol/v6/QueryParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryParams", - "required": [ - "operation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/QueryResult.json b/packages/protocol/schema/QueryResult.json deleted file mode 100644 index 85bdf32cc..000000000 --- a/packages/protocol/schema/QueryResult.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "type": "object", - "properties": { - "result": true, - "content": { - "type": [ - "null", - "object" - ], - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "root_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/QueryResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QueryResult", - "additionalProperties": false -} diff --git a/packages/protocol/schema/QuestionAnswerParams.json b/packages/protocol/schema/QuestionAnswerParams.json deleted file mode 100644 index 9f58209d0..000000000 --- a/packages/protocol/schema/QuestionAnswerParams.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - }, - "answers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/QuestionAnswerParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "QuestionAnswerParams", - "required": [ - "id", - "answer", - "dismissed" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RPCError.json b/packages/protocol/schema/RPCError.json deleted file mode 100644 index 459494c1e..000000000 --- a/packages/protocol/schema/RPCError.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "type": "object", - "properties": { - "data": { - "type": [ - "null", - "object" - ], - "properties": { - "kind": { - "type": "string" - } - }, - "required": [ - "kind" - ], - "additionalProperties": false - }, - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/RPCError", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RPCError", - "required": [ - "code", - "message" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ReplayParams.json b/packages/protocol/schema/ReplayParams.json deleted file mode 100644 index 767d718ff..000000000 --- a/packages/protocol/schema/ReplayParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ReplayParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ReplayParams", - "required": [ - "root_id", - "cursor" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ReplayResult.json b/packages/protocol/schema/ReplayResult.json deleted file mode 100644 index aaf8eb557..000000000 --- a/packages/protocol/schema/ReplayResult.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "object", - "properties": { - "events": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "subscription_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "payload": true - }, - "required": [ - "root_id", - "seq", - "kind" - ], - "additionalProperties": false - } - }, - "latest": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "expired": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ReplayResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ReplayResult", - "required": [ - "events", - "latest" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/Resolved.json b/packages/protocol/schema/Resolved.json deleted file mode 100644 index dd120af15..000000000 --- a/packages/protocol/schema/Resolved.json +++ /dev/null @@ -1,248 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "dark": { - "type": "boolean" - }, - "colors": { - "type": "object", - "properties": { - "background": { - "type": "string" - }, - "foreground": { - "type": "string" - }, - "muted": { - "type": "string" - }, - "faint": { - "type": "string" - }, - "primary": { - "type": "string" - }, - "on_primary": { - "type": "string" - }, - "accent": { - "type": "string" - }, - "success": { - "type": "string" - }, - "warning": { - "type": "string" - }, - "error": { - "type": "string" - }, - "info": { - "type": "string" - }, - "link": { - "type": "string" - }, - "emphasis": { - "type": "string" - }, - "border": { - "type": "string" - }, - "border_focus": { - "type": "string" - }, - "diff_add": { - "type": "string" - }, - "diff_del": { - "type": "string" - }, - "panel": { - "type": "string" - }, - "element": { - "type": "string" - }, - "hover": { - "type": "string" - } - }, - "required": [ - "background", - "foreground", - "muted", - "faint", - "primary", - "on_primary", - "accent", - "success", - "warning", - "error", - "info", - "link", - "emphasis", - "border", - "border_focus", - "diff_add", - "diff_del", - "panel", - "element", - "hover" - ], - "additionalProperties": false - }, - "syntax": { - "type": "object", - "properties": { - "keyword": { - "type": "string" - }, - "string": { - "type": "string" - }, - "number": { - "type": "string" - }, - "comment": { - "type": "string" - }, - "function": { - "type": "string" - }, - "type": { - "type": "string" - }, - "operator": { - "type": "string" - }, - "punctuation": { - "type": "string" - } - }, - "required": [ - "keyword", - "string", - "number", - "comment", - "function", - "type", - "operator", - "punctuation" - ], - "additionalProperties": false - }, - "markdown": { - "type": "object", - "properties": { - "heading": { - "type": "string" - }, - "strong": { - "type": "string" - }, - "code": { - "type": "string" - }, - "quote": { - "type": "string" - } - }, - "required": [ - "heading", - "strong", - "code", - "quote" - ], - "additionalProperties": false - }, - "code": { - "type": "object", - "properties": { - "foreground": { - "type": "string" - }, - "background": { - "type": "string" - }, - "tokens": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "color": { - "type": "string" - }, - "background": { - "type": "string" - }, - "bold": { - "type": "boolean" - }, - "italic": { - "type": "boolean" - }, - "underline": { - "type": "boolean" - } - }, - "required": [ - "color", - "background", - "bold", - "italic", - "underline" - ], - "additionalProperties": false - } - } - }, - "required": [ - "foreground", - "background", - "tokens" - ], - "additionalProperties": false - }, - "web": { - "type": [ - "null", - "object" - ], - "properties": { - "navigation": { - "type": "string" - }, - "quiet_border": { - "type": "string" - }, - "code_background": { - "type": "string" - }, - "inline_code_background": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/Resolved", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Resolved", - "required": [ - "id", - "name", - "dark", - "colors", - "syntax", - "markdown", - "code" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RestartNotice.json b/packages/protocol/schema/RestartNotice.json deleted file mode 100644 index eaaa3799d..000000000 --- a/packages/protocol/schema/RestartNotice.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "type": "object", - "properties": { - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cursors": { - "type": "object", - "additionalProperties": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - } - }, - "$id": "https://whip.dev/protocol/v6/RestartNotice", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RestartNotice", - "required": [ - "generation", - "cursors" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RestartParams.json b/packages/protocol/schema/RestartParams.json deleted file mode 100644 index 6d360ce13..000000000 --- a/packages/protocol/schema/RestartParams.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "object", - "properties": { - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/RestartParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RestartParams", - "required": [ - "generation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RewindParams.json b/packages/protocol/schema/RewindParams.json deleted file mode 100644 index 1cbbe9d4d..000000000 --- a/packages/protocol/schema/RewindParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "expected_revision": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cut": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/RewindParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RewindParams", - "required": [ - "expected_revision", - "cut" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RewindResult.json b/packages/protocol/schema/RewindResult.json deleted file mode 100644 index 319f0cadb..000000000 --- a/packages/protocol/schema/RewindResult.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "cut": { - "type": "integer" - }, - "restored_files": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/RewindResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RewindResult", - "required": [ - "cut", - "restored_files" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RootCollectionPage.json b/packages/protocol/schema/RootCollectionPage.json deleted file mode 100644 index 28ff50d6b..000000000 --- a/packages/protocol/schema/RootCollectionPage.json +++ /dev/null @@ -1,1931 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "collection": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "event_cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "items": { - "type": [ - "null", - "array" - ], - "items": { - "allOf": [ - { - "type": "object", - "properties": { - "agent": { - "type": [ - "null", - "object" - ], - "properties": { - "execution_engine": { - "type": "string" - }, - "last_turn": { - "type": [ - "null", - "object" - ], - "properties": { - "turn_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "event_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "error": { - "type": "string" - }, - "error_truncated": { - "type": "boolean" - }, - "error_details": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "model_calls": { - "type": "integer" - }, - "compactions": { - "type": "integer" - }, - "last_activity_at": { - "type": "string" - } - }, - "required": [ - "status", - "event_seq" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "report": { - "type": "string" - }, - "status": { - "type": "string" - }, - "pending_mail": { - "type": "integer" - }, - "lifecycle_phase": { - "type": "string" - }, - "blocking_reason": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "allowed_controls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "execution_engine", - "id", - "root_id", - "parent_id", - "name", - "model", - "provider", - "effort", - "cwd", - "report", - "status", - "pending_mail", - "lifecycle_phase", - "blocking_reason", - "terminal_cause", - "allowed_controls" - ], - "additionalProperties": false - }, - "inbox": { - "type": [ - "null", - "object" - ], - "properties": { - "delivery_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "origin": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "steer_turn_id": { - "type": "string" - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "text": { - "type": "string" - }, - "truncated": { - "type": "boolean" - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "content": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - }, - "attachment_count": { - "type": "integer" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "status": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "root_id", - "agent_id", - "seq", - "kind", - "status", - "payload" - ], - "additionalProperties": false - }, - "blackboard": { - "type": [ - "null", - "object" - ], - "properties": { - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "author_agent_id": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "key", - "version", - "author_agent_id", - "payload" - ], - "additionalProperties": false - }, - "budget": { - "type": [ - "null", - "object" - ], - "properties": { - "agent_id": { - "type": "string" - }, - "state": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "limit": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "remaining": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "uncertain": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "incomplete": { - "type": "boolean" - } - }, - "required": [ - "kind", - "limit", - "used", - "reserved", - "remaining", - "uncertain", - "incomplete" - ], - "additionalProperties": false - } - }, - "required": [ - "agent_id", - "state" - ], - "additionalProperties": false - }, - "capability": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "issuer_agent_id": { - "type": "string" - }, - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "scopes": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "file_scope": { - "type": "string" - }, - "file_issuer_id": { - "type": "string" - }, - "file_issuer_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "mcp": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "server": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "definition": { - "type": "string" - } - }, - "required": [ - "server", - "tool", - "definition" - ], - "additionalProperties": false - } - }, - "mcp_all": { - "type": "boolean" - }, - "browser": { - "type": [ - "null", - "object" - ], - "properties": { - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "rights": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "provider_id", - "provider_epoch", - "tab_id", - "tab_generation", - "profile_id", - "rights" - ], - "additionalProperties": false - }, - "browser_issuer_id": { - "type": "string" - }, - "browser_issuer_generation": { - "type": "integer" - }, - "browser_delegation_only": { - "type": "boolean" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": [ - "id", - "root_id", - "agent_id", - "issuer_agent_id", - "operations", - "scopes", - "mcp", - "mcp_all", - "generation", - "status", - "expires_at", - "created_at", - "updated_at" - ], - "additionalProperties": false - }, - "schedule": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "integer" - }, - "schedule": { - "type": "string" - }, - "prompt": { - "type": "string" - }, - "anchor": { - "type": "string" - }, - "last_fire": { - "type": "string" - } - }, - "required": [ - "id", - "schedule", - "prompt", - "anchor", - "last_fire" - ], - "additionalProperties": false - }, - "permission": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "capability_id": { - "type": "string" - }, - "capability_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - } - }, - "required": [ - "id", - "agent_id", - "operation_id", - "operation", - "canonical_path", - "request_digest", - "capability_id", - "capability_generation", - "status", - "command", - "rule" - ], - "additionalProperties": false - }, - "body": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "additionalProperties": false - }, - { - "oneOf": [ - { - "type": "object", - "properties": { - "agent": { - "type": [ - "null", - "object" - ], - "properties": { - "execution_engine": { - "type": "string" - }, - "last_turn": { - "type": [ - "null", - "object" - ], - "properties": { - "turn_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "event_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "error": { - "type": "string" - }, - "error_truncated": { - "type": "boolean" - }, - "error_details": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "model_calls": { - "type": "integer" - }, - "compactions": { - "type": "integer" - }, - "last_activity_at": { - "type": "string" - } - }, - "required": [ - "status", - "event_seq" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "report": { - "type": "string" - }, - "status": { - "type": "string" - }, - "pending_mail": { - "type": "integer" - }, - "lifecycle_phase": { - "type": "string" - }, - "blocking_reason": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "allowed_controls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "execution_engine", - "id", - "root_id", - "parent_id", - "name", - "model", - "provider", - "effort", - "cwd", - "report", - "status", - "pending_mail", - "lifecycle_phase", - "blocking_reason", - "terminal_cause", - "allowed_controls" - ], - "additionalProperties": false - } - }, - "required": [ - "agent" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inbox": { - "type": [ - "null", - "object" - ], - "properties": { - "delivery_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "origin": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "steer_turn_id": { - "type": "string" - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "text": { - "type": "string" - }, - "truncated": { - "type": "boolean" - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "content": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - }, - "attachment_count": { - "type": "integer" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "status": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "root_id", - "agent_id", - "seq", - "kind", - "status", - "payload" - ], - "additionalProperties": false - } - }, - "required": [ - "inbox" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "blackboard": { - "type": [ - "null", - "object" - ], - "properties": { - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "author_agent_id": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "key", - "version", - "author_agent_id", - "payload" - ], - "additionalProperties": false - } - }, - "required": [ - "blackboard" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "budget": { - "type": [ - "null", - "object" - ], - "properties": { - "agent_id": { - "type": "string" - }, - "state": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "limit": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "remaining": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "uncertain": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "incomplete": { - "type": "boolean" - } - }, - "required": [ - "kind", - "limit", - "used", - "reserved", - "remaining", - "uncertain", - "incomplete" - ], - "additionalProperties": false - } - }, - "required": [ - "agent_id", - "state" - ], - "additionalProperties": false - } - }, - "required": [ - "budget" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "capability": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "issuer_agent_id": { - "type": "string" - }, - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "scopes": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "file_scope": { - "type": "string" - }, - "file_issuer_id": { - "type": "string" - }, - "file_issuer_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "mcp": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "server": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "definition": { - "type": "string" - } - }, - "required": [ - "server", - "tool", - "definition" - ], - "additionalProperties": false - } - }, - "mcp_all": { - "type": "boolean" - }, - "browser": { - "type": [ - "null", - "object" - ], - "properties": { - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "rights": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "provider_id", - "provider_epoch", - "tab_id", - "tab_generation", - "profile_id", - "rights" - ], - "additionalProperties": false - }, - "browser_issuer_id": { - "type": "string" - }, - "browser_issuer_generation": { - "type": "integer" - }, - "browser_delegation_only": { - "type": "boolean" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": [ - "id", - "root_id", - "agent_id", - "issuer_agent_id", - "operations", - "scopes", - "mcp", - "mcp_all", - "generation", - "status", - "expires_at", - "created_at", - "updated_at" - ], - "additionalProperties": false - } - }, - "required": [ - "capability" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "schedule": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "integer" - }, - "schedule": { - "type": "string" - }, - "prompt": { - "type": "string" - }, - "anchor": { - "type": "string" - }, - "last_fire": { - "type": "string" - } - }, - "required": [ - "id", - "schedule", - "prompt", - "anchor", - "last_fire" - ], - "additionalProperties": false - } - }, - "required": [ - "schedule" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "permission": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "capability_id": { - "type": "string" - }, - "capability_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - } - }, - "required": [ - "id", - "agent_id", - "operation_id", - "operation", - "canonical_path", - "request_digest", - "capability_id", - "capability_generation", - "status", - "command", - "rule" - ], - "additionalProperties": false - } - }, - "required": [ - "permission" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "body": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "body" - ], - "additionalProperties": false - } - ] - } - ] - } - }, - "next_cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "collection": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "collection", - "revision", - "offset" - ], - "additionalProperties": false - }, - "has_more": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/RootCollectionPage", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RootCollectionPage", - "required": [ - "root_id", - "collection", - "revision", - "event_cursor", - "items", - "has_more" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RootCollectionParams.json b/packages/protocol/schema/RootCollectionParams.json deleted file mode 100644 index 13bed65fa..000000000 --- a/packages/protocol/schema/RootCollectionParams.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "collection": { - "type": "string" - }, - "cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "collection": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "collection", - "revision", - "offset" - ], - "additionalProperties": false - }, - "limit": { - "type": "integer" - }, - "max_bytes": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/RootCollectionParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RootCollectionParams", - "required": [ - "root_id", - "collection", - "limit", - "max_bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RootIDResult.json b/packages/protocol/schema/RootIDResult.json deleted file mode 100644 index 0bec9f417..000000000 --- a/packages/protocol/schema/RootIDResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/RootIDResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RootIDResult", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RootParams.json b/packages/protocol/schema/RootParams.json deleted file mode 100644 index 11d5942f3..000000000 --- a/packages/protocol/schema/RootParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/RootParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RootParams", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RootSnapshot.json b/packages/protocol/schema/RootSnapshot.json deleted file mode 100644 index e6401929c..000000000 --- a/packages/protocol/schema/RootSnapshot.json +++ /dev/null @@ -1,1915 +0,0 @@ -{ - "type": "object", - "properties": { - "collection_revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "active_turns": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "omitted": { - "type": "object", - "additionalProperties": { - "type": "boolean" - } - }, - "message_seqs": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - }, - "first_message_seq": { - "type": "integer" - }, - "history_revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "meta": { - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "definition_revision": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "title": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "goal": { - "type": "string" - }, - "forked_from": { - "type": "string" - }, - "fork_seq": { - "type": "integer" - }, - "tags": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "archived": { - "type": "boolean" - }, - "pinned": { - "type": "boolean" - }, - "effort": { - "type": "string" - }, - "usage_in": { - "type": "integer" - }, - "usage_cached": { - "type": "integer" - }, - "usage_out": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - }, - "required": [ - "execution_engine", - "definition", - "definition_revision", - "id", - "kind", - "title", - "model", - "provider", - "cwd", - "goal", - "forked_from", - "fork_seq", - "tags", - "archived", - "pinned", - "effort", - "usage_in", - "usage_cached", - "usage_out", - "updated_at" - ], - "additionalProperties": false - }, - "messages": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "presentation": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - }, - "context_part_index": { - "type": "integer" - }, - "screenshot_part_index": { - "type": [ - "null", - "integer" - ] - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count", - "context_part_index" - ], - "additionalProperties": false - }, - "version": { - "type": "integer" - }, - "turn_id": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "start": { - "type": "integer" - }, - "end": { - "type": "integer" - }, - "text": { - "type": "string" - }, - "tool_name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "call_id": { - "type": "string" - }, - "hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "summary": { - "type": "string" - }, - "status": { - "type": "string" - }, - "duration": { - "type": "string" - }, - "error": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "required": [ - "invocation_id", - "name", - "status" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "id", - "kind" - ], - "additionalProperties": false - } - }, - "omitted": { - "type": "integer" - } - }, - "required": [ - "version" - ], - "additionalProperties": false - }, - "role": { - "type": "string" - }, - "content": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "text": { - "type": "string" - }, - "image_url": { - "type": [ - "null", - "object" - ], - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false - }, - "w": { - "type": "integer" - }, - "h": { - "type": "integer" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - } - ] - }, - "tool_calls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "arguments": { - "type": "string" - } - }, - "required": [ - "name", - "arguments" - ], - "additionalProperties": false - }, - "duration_ms": { - "type": "integer" - }, - "exit_code": { - "type": "integer" - } - }, - "required": [ - "id", - "type", - "function" - ], - "additionalProperties": false - } - }, - "tool_call_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "authored": { - "type": "boolean" - }, - "sent_at": { - "type": [ - "null", - "string" - ] - }, - "usage": { - "type": [ - "null", - "object" - ], - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - }, - "model": { - "type": "string" - }, - "rewound_from": { - "type": "string" - }, - "call_id": { - "type": "string" - } - }, - "required": [ - "role", - "content" - ], - "additionalProperties": false - } - }, - "presentation": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "payload": true - }, - "required": [ - "seq", - "kind", - "payload" - ], - "additionalProperties": false - } - }, - "agent_presentations": { - "type": "object", - "additionalProperties": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "payload": true - }, - "required": [ - "seq", - "kind", - "payload" - ], - "additionalProperties": false - } - } - }, - "agents": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "last_turn": { - "type": [ - "null", - "object" - ], - "properties": { - "turn_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "started_at": { - "type": "string" - }, - "finished_at": { - "type": "string" - }, - "event_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "error": { - "type": "string" - }, - "error_truncated": { - "type": "boolean" - }, - "error_details": { - "type": [ - "null", - "object" - ], - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - }, - "model_calls": { - "type": "integer" - }, - "compactions": { - "type": "integer" - }, - "last_activity_at": { - "type": "string" - } - }, - "required": [ - "status", - "event_seq" - ], - "additionalProperties": false - }, - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "report": { - "type": "string" - }, - "status": { - "type": "string" - }, - "pending_mail": { - "type": "integer" - }, - "lifecycle_phase": { - "type": "string" - }, - "blocking_reason": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "allowed_controls": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - } - }, - "required": [ - "execution_engine", - "id", - "root_id", - "parent_id", - "name", - "model", - "provider", - "effort", - "cwd", - "report", - "status", - "pending_mail", - "lifecycle_phase", - "blocking_reason", - "terminal_cause", - "allowed_controls" - ], - "additionalProperties": false - } - }, - "inbox": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "delivery_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "origin": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "steer_turn_id": { - "type": "string" - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "text": { - "type": "string" - }, - "truncated": { - "type": "boolean" - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "content": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - }, - "attachment_count": { - "type": "integer" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "kind": { - "type": "string" - }, - "status": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "root_id", - "agent_id", - "seq", - "kind", - "status", - "payload" - ], - "additionalProperties": false - } - }, - "blackboard": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "author_agent_id": { - "type": "string" - }, - "payload": { - "type": "object", - "properties": { - "inline": true, - "text": { - "type": [ - "null", - "string" - ] - }, - "binary": { - "type": [ - "string", - "null" - ], - "contentEncoding": "base64" - }, - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size", - "media_type", - "source" - ], - "additionalProperties": false - } - }, - "required": [ - "key", - "version", - "author_agent_id", - "payload" - ], - "additionalProperties": false - } - }, - "budgets": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "agent_id": { - "type": "string" - }, - "state": { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "limit": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "remaining": { - "type": [ - "string", - "null" - ], - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "uncertain": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "incomplete": { - "type": "boolean" - } - }, - "required": [ - "kind", - "limit", - "used", - "reserved", - "remaining", - "uncertain", - "incomplete" - ], - "additionalProperties": false - } - }, - "required": [ - "agent_id", - "state" - ], - "additionalProperties": false - } - }, - "accounting": { - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "unknown_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "scope", - "revision", - "reported_cost_micros", - "estimated_cost_micros", - "reported_cost_calls", - "estimated_cost_calls", - "unknown_cost_calls", - "reported_calls", - "estimated_calls", - "pending_calls" - ], - "additionalProperties": false - }, - "capabilities": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "issuer_agent_id": { - "type": "string" - }, - "operations": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "scopes": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "file_scope": { - "type": "string" - }, - "file_issuer_id": { - "type": "string" - }, - "file_issuer_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "mcp": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "server": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "definition": { - "type": "string" - } - }, - "required": [ - "server", - "tool", - "definition" - ], - "additionalProperties": false - } - }, - "mcp_all": { - "type": "boolean" - }, - "browser": { - "type": [ - "null", - "object" - ], - "properties": { - "provider_id": { - "type": "string" - }, - "provider_epoch": { - "type": "string" - }, - "tab_id": { - "type": "string" - }, - "tab_generation": { - "type": "string" - }, - "profile_id": { - "type": "string" - }, - "attachment_id": { - "type": "string" - }, - "attachment_generation": { - "type": "string" - }, - "rights": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "preview": { - "type": [ - "null", - "object" - ], - "properties": { - "host_id": { - "type": "string" - }, - "host_identity": { - "type": "string" - }, - "connection_generation": { - "type": "string" - }, - "environment_id": { - "type": "string" - }, - "loopback": { - "type": "string" - }, - "ports": { - "type": [ - "null", - "array" - ], - "items": { - "type": "integer" - } - } - }, - "required": [ - "host_id", - "host_identity", - "connection_generation", - "environment_id", - "loopback", - "ports" - ], - "additionalProperties": false - } - }, - "required": [ - "provider_id", - "provider_epoch", - "tab_id", - "tab_generation", - "profile_id", - "rights" - ], - "additionalProperties": false - }, - "browser_issuer_id": { - "type": "string" - }, - "browser_issuer_generation": { - "type": "integer" - }, - "browser_delegation_only": { - "type": "boolean" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": [ - "id", - "root_id", - "agent_id", - "issuer_agent_id", - "operations", - "scopes", - "mcp", - "mcp_all", - "generation", - "status", - "expires_at", - "created_at", - "updated_at" - ], - "additionalProperties": false - } - }, - "schedules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "schedule": { - "type": "string" - }, - "prompt": { - "type": "string" - }, - "anchor": { - "type": "string" - }, - "last_fire": { - "type": "string" - } - }, - "required": [ - "id", - "schedule", - "prompt", - "anchor", - "last_fire" - ], - "additionalProperties": false - } - }, - "upcoming_schedules": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "next_fire": { - "type": "string" - }, - "prompt": { - "type": "string" - }, - "prompt_truncated": { - "type": "boolean" - } - }, - "required": [ - "id", - "next_fire", - "prompt" - ], - "additionalProperties": false - } - }, - "upcoming_schedule_count": { - "type": [ - "null", - "integer" - ] - }, - "permissions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "capability_id": { - "type": "string" - }, - "capability_generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "status": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - } - }, - "required": [ - "id", - "agent_id", - "operation_id", - "operation", - "canonical_path", - "request_digest", - "capability_id", - "capability_generation", - "status", - "command", - "rule" - ], - "additionalProperties": false - } - }, - "questions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "turn_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "sender_agent_id": { - "type": "string" - }, - "inbox_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "inbox_kind": { - "type": "string" - }, - "delivery": { - "type": "string" - }, - "message_id": { - "type": "string" - }, - "phase": { - "type": "string" - }, - "status": { - "type": "string" - }, - "terminal_cause": { - "type": "string" - }, - "command_client_id": { - "type": "string" - }, - "command_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "schedule_id": { - "type": "integer" - }, - "slot": { - "type": "string" - }, - "error": { - "type": "string" - }, - "model_call": { - "type": [ - "null", - "object" - ], - "properties": { - "id": { - "type": "string" - }, - "logical_id": { - "type": "string" - }, - "number": { - "type": "integer" - }, - "purpose": { - "type": "string" - }, - "usage_source": { - "type": "string" - }, - "cost_source": { - "type": "string" - }, - "tokens": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "elapsed_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "exhausted": { - "type": "boolean" - } - }, - "required": [ - "id", - "logical_id", - "number", - "purpose", - "usage_source", - "cost_source", - "tokens", - "cost_micros", - "elapsed_millis", - "exhausted" - ], - "additionalProperties": false - }, - "acknowledged_inbox": { - "type": "array", - "items": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "subscription_id": { - "type": "string" - }, - "key": { - "type": "string" - }, - "version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "expected_version": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "not_restored": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "required": [ - "name", - "reason" - ], - "additionalProperties": false - } - }, - "attempt": { - "type": "string" - }, - "budget_kind": { - "type": "string" - }, - "amount": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "used": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reserved": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "capability_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "permission_id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "canonical_path": { - "type": "string" - }, - "request_digest": { - "type": "string" - }, - "command": { - "type": "string" - }, - "rule": { - "type": "string" - }, - "rule_source": { - "type": "string" - }, - "question_id": { - "type": "string" - }, - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - }, - "questions": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "question": { - "type": "string" - }, - "options": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "description": { - "type": "string" - }, - "recommended": { - "type": "boolean" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "multiple": { - "type": "boolean" - } - }, - "required": [ - "question" - ], - "additionalProperties": false - } - }, - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - }, - "answers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "answer": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "dismissed": { - "type": "boolean" - } - }, - "additionalProperties": false - } - } - }, - "additionalProperties": false - } - }, - "permission_mode": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/RootSnapshot", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RootSnapshot", - "required": [ - "active_turns", - "message_seqs", - "history_revision", - "root_id", - "cursor", - "meta", - "messages", - "presentation", - "agent_presentations", - "agents", - "inbox", - "blackboard", - "budgets", - "capabilities", - "schedules", - "permissions", - "questions" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/RunConfigureParams.json b/packages/protocol/schema/RunConfigureParams.json deleted file mode 100644 index 13d11a0b1..000000000 --- a/packages/protocol/schema/RunConfigureParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "system": { - "type": "string" - }, - "max_turns": { - "type": "integer" - }, - "headless": { - "type": "boolean" - }, - "cache_key": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/RunConfigureParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RunConfigureParams", - "additionalProperties": false -} diff --git a/packages/protocol/schema/RuntimeConfiguration.json b/packages/protocol/schema/RuntimeConfiguration.json deleted file mode 100644 index c922a4dd1..000000000 --- a/packages/protocol/schema/RuntimeConfiguration.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "type": "object", - "properties": { - "default_execution_engine": { - "type": "string" - }, - "disabled_providers": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "discovery": { - "type": [ - "null", - "object" - ], - "properties": { - "status": { - "type": "string" - }, - "message": { - "type": "string" - }, - "model_count": { - "type": "integer" - } - }, - "required": [ - "status" - ], - "additionalProperties": false - }, - "remote_hosts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "runtime_id": { - "type": "string" - }, - "connect_on_launch": { - "type": "boolean" - } - }, - "required": [ - "id", - "name", - "url", - "runtime_id", - "connect_on_launch" - ], - "additionalProperties": false - } - }, - "import_claude": { - "type": "boolean" - }, - "import_codex": { - "type": "boolean" - }, - "mcp_import_offered": { - "type": "boolean" - }, - "brand_icons": { - "type": "boolean" - }, - "revision": { - "type": "string" - }, - "default_model": { - "type": "string" - }, - "default_provider": { - "type": "string" - }, - "default_effort": { - "type": "string" - }, - "default_permission_mode": { - "type": "string" - }, - "compact_model": { - "type": "string" - }, - "compact_provider": { - "type": "string" - }, - "compact_percent": { - "type": "integer" - }, - "goal_max_rounds": { - "type": "integer" - }, - "max_retries": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/RuntimeConfiguration", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "RuntimeConfiguration", - "required": [ - "default_execution_engine", - "import_claude", - "import_codex", - "mcp_import_offered", - "brand_icons", - "revision", - "default_model", - "default_provider", - "default_effort", - "compact_model", - "compact_provider", - "compact_percent", - "goal_max_rounds", - "max_retries" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ScheduleCreateParams.json b/packages/protocol/schema/ScheduleCreateParams.json deleted file mode 100644 index 19238bfbb..000000000 --- a/packages/protocol/schema/ScheduleCreateParams.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "object", - "properties": { - "schedule": { - "type": "string" - }, - "prompt": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ScheduleCreateParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ScheduleCreateParams", - "required": [ - "schedule", - "prompt" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ScheduleDeleteParams.json b/packages/protocol/schema/ScheduleDeleteParams.json deleted file mode 100644 index abed6d190..000000000 --- a/packages/protocol/schema/ScheduleDeleteParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "schedule_id": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ScheduleDeleteParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ScheduleDeleteParams", - "required": [ - "schedule_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ScheduleListResult.json b/packages/protocol/schema/ScheduleListResult.json deleted file mode 100644 index 30d699d6a..000000000 --- a/packages/protocol/schema/ScheduleListResult.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "schedule": { - "type": "string" - }, - "prompt": { - "type": "string" - }, - "anchor": { - "type": "string" - }, - "last_fire": { - "type": "string" - } - }, - "required": [ - "id", - "schedule", - "prompt", - "anchor", - "last_fire" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/ScheduleListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ScheduleListResult" -} diff --git a/packages/protocol/schema/ScheduleResult.json b/packages/protocol/schema/ScheduleResult.json deleted file mode 100644 index 9309a1201..000000000 --- a/packages/protocol/schema/ScheduleResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "schedule_id": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/ScheduleResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ScheduleResult", - "required": [ - "schedule_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionCatalogPage.json b/packages/protocol/schema/SessionCatalogPage.json deleted file mode 100644 index 15a3e491f..000000000 --- a/packages/protocol/schema/SessionCatalogPage.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "type": "object", - "properties": { - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "items": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "title": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "workspace_id": { - "type": "string" - }, - "pinned": { - "type": "boolean" - }, - "archived": { - "type": "boolean" - }, - "updated_at": { - "type": "string" - }, - "truncated": { - "type": "boolean" - } - }, - "required": [ - "id", - "kind", - "title", - "model", - "provider", - "cwd", - "pinned", - "archived", - "updated_at", - "truncated" - ], - "additionalProperties": false - } - }, - "next_cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "search": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "archived", - "all" - ] - } - }, - "required": [ - "revision", - "offset", - "status" - ], - "additionalProperties": false - }, - "has_more": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/SessionCatalogPage", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionCatalogPage", - "required": [ - "revision", - "items", - "has_more" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionCatalogParams.json b/packages/protocol/schema/SessionCatalogParams.json deleted file mode 100644 index 2befb95dd..000000000 --- a/packages/protocol/schema/SessionCatalogParams.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "type": "object", - "properties": { - "search": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "archived", - "all" - ] - }, - "cursor": { - "type": [ - "null", - "object" - ], - "properties": { - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "search": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "active", - "archived", - "all" - ] - } - }, - "required": [ - "revision", - "offset", - "status" - ], - "additionalProperties": false - }, - "limit": { - "type": "integer" - }, - "max_bytes": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/SessionCatalogParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionCatalogParams", - "required": [ - "limit", - "max_bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionListResult.json b/packages/protocol/schema/SessionListResult.json deleted file mode 100644 index 10fe53105..000000000 --- a/packages/protocol/schema/SessionListResult.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "execution_engine": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "definition_revision": { - "type": "string" - }, - "id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "title": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "goal": { - "type": "string" - }, - "forked_from": { - "type": "string" - }, - "fork_seq": { - "type": "integer" - }, - "tags": { - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - } - }, - "archived": { - "type": "boolean" - }, - "pinned": { - "type": "boolean" - }, - "effort": { - "type": "string" - }, - "usage_in": { - "type": "integer" - }, - "usage_cached": { - "type": "integer" - }, - "usage_out": { - "type": "integer" - }, - "updated_at": { - "type": "string" - } - }, - "required": [ - "execution_engine", - "definition", - "definition_revision", - "id", - "kind", - "title", - "model", - "provider", - "cwd", - "goal", - "forked_from", - "fork_seq", - "tags", - "archived", - "pinned", - "effort", - "usage_in", - "usage_cached", - "usage_out", - "updated_at" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/SessionListResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionListResult" -} diff --git a/packages/protocol/schema/SessionMetadata.json b/packages/protocol/schema/SessionMetadata.json deleted file mode 100644 index 0f5cff063..000000000 --- a/packages/protocol/schema/SessionMetadata.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "history_revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "archived": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/SessionMetadata", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionMetadata", - "required": [ - "root_id", - "title", - "cwd", - "history_revision", - "archived" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionPreviewResult.json b/packages/protocol/schema/SessionPreviewResult.json deleted file mode 100644 index b9d7e002f..000000000 --- a/packages/protocol/schema/SessionPreviewResult.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "user": { - "type": "string" - }, - "assistant": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/SessionPreviewResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionPreviewResult", - "required": [ - "root_id", - "user", - "assistant" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionSummariesParams.json b/packages/protocol/schema/SessionSummariesParams.json deleted file mode 100644 index 36adadd4e..000000000 --- a/packages/protocol/schema/SessionSummariesParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "root_ids": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[\\s\\S]{1,256}$" - }, - "maxItems": 32, - "uniqueItems": true - } - }, - "$id": "https://whip.dev/protocol/v6/SessionSummariesParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionSummariesParams", - "required": [ - "root_ids" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionSummariesResult.json b/packages/protocol/schema/SessionSummariesResult.json deleted file mode 100644 index 96881b300..000000000 --- a/packages/protocol/schema/SessionSummariesResult.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "type": "object", - "properties": { - "items": { - "type": "array", - "items": { - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "missing": { - "type": "boolean" - }, - "archived": { - "type": "boolean" - }, - "title": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "workspace_id": { - "type": "string" - }, - "running_agents": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "queued_agents": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_permissions": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_questions": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "truncated": { - "type": "boolean" - } - }, - "required": [ - "root_id", - "missing", - "archived", - "title", - "cwd", - "running_agents", - "queued_agents", - "pending_permissions", - "pending_questions", - "truncated" - ], - "additionalProperties": false - }, - "maxItems": 32 - } - }, - "$id": "https://whip.dev/protocol/v6/SessionSummariesResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionSummariesResult", - "required": [ - "items" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionTitleChangedParams.json b/packages/protocol/schema/SessionTitleChangedParams.json deleted file mode 100644 index 623cc0c2a..000000000 --- a/packages/protocol/schema/SessionTitleChangedParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/SessionTitleChangedParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionTitleChangedParams", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SessionUpdateEvent.json b/packages/protocol/schema/SessionUpdateEvent.json deleted file mode 100644 index 71b627e3f..000000000 --- a/packages/protocol/schema/SessionUpdateEvent.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "type": "object", - "properties": { - "archived": { - "type": [ - "null", - "boolean" - ] - }, - "title": { - "type": "string" - }, - "model": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "effort": { - "type": "string" - }, - "effort_changed": { - "type": "boolean" - }, - "working_directory": { - "type": "string" - }, - "permission_mode": { - "type": [ - "null", - "string" - ] - } - }, - "$id": "https://whip.dev/protocol/v6/SessionUpdateEvent", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SessionUpdateEvent", - "additionalProperties": false -} diff --git a/packages/protocol/schema/ShellParams.json b/packages/protocol/schema/ShellParams.json deleted file mode 100644 index 3aa3d0905..000000000 --- a/packages/protocol/schema/ShellParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "command": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ShellParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ShellParams", - "required": [ - "command" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SnapshotParams.json b/packages/protocol/schema/SnapshotParams.json deleted file mode 100644 index 0817fc303..000000000 --- a/packages/protocol/schema/SnapshotParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/SnapshotParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SnapshotParams", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SpanPage.json b/packages/protocol/schema/SpanPage.json deleted file mode 100644 index 9a69957e0..000000000 --- a/packages/protocol/schema/SpanPage.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "spans": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "start_ns": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "end_ns": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "attrs": true, - "links": true, - "updated_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "id", - "trace_id", - "root_id", - "agent_id", - "kind", - "name", - "status", - "start_ns", - "end_ns", - "updated_seq" - ], - "additionalProperties": false - } - }, - "next_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "has_more": { - "type": "boolean" - }, - "server_time_ns": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/SpanPage", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SpanPage", - "required": [ - "root_id", - "spans", - "next_seq", - "has_more", - "server_time_ns" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SpanRecord.json b/packages/protocol/schema/SpanRecord.json deleted file mode 100644 index dd692cbe4..000000000 --- a/packages/protocol/schema/SpanRecord.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "parent_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "kind": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "start_ns": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "end_ns": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "attrs": true, - "links": true, - "updated_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/SpanRecord", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SpanRecord", - "required": [ - "id", - "trace_id", - "root_id", - "agent_id", - "kind", - "name", - "status", - "start_ns", - "end_ns", - "updated_seq" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/StreamEvent.json b/packages/protocol/schema/StreamEvent.json deleted file mode 100644 index 3279efd91..000000000 --- a/packages/protocol/schema/StreamEvent.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "type": "object", - "properties": { - "part_id": { - "type": "string" - }, - "display": { - "type": [ - "null", - "object" - ], - "properties": { - "target": { - "type": "string" - }, - "command": { - "type": "string" - }, - "query": { - "type": "string" - }, - "child_id": { - "type": "string" - }, - "label": { - "type": "string" - } - }, - "additionalProperties": false - }, - "accounting": { - "type": [ - "null", - "object" - ], - "properties": { - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "scope": { - "type": "string" - }, - "revision": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_micros": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "unknown_cost_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reported_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "estimated_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "pending_calls": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "required": [ - "root_id", - "agent_id", - "scope", - "revision", - "reported_cost_micros", - "estimated_cost_micros", - "reported_cost_calls", - "estimated_cost_calls", - "unknown_cost_calls", - "reported_calls", - "estimated_calls", - "pending_calls" - ], - "additionalProperties": false - }, - "usage": { - "type": [ - "null", - "object" - ], - "properties": { - "used": { - "type": "integer" - }, - "size": { - "type": "integer" - }, - "usage": { - "type": "object", - "properties": { - "reported": { - "type": "boolean" - }, - "cost": { - "type": [ - "null", - "number" - ] - }, - "prompt_tokens": { - "type": "integer" - }, - "completion_tokens": { - "type": "integer" - }, - "prompt_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "cached_tokens": { - "type": "integer" - } - }, - "required": [ - "cached_tokens" - ], - "additionalProperties": false - }, - "completion_tokens_details": { - "type": [ - "null", - "object" - ], - "properties": { - "reasoning_tokens": { - "type": "integer" - } - }, - "required": [ - "reasoning_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "prompt_tokens", - "completion_tokens" - ], - "additionalProperties": false - } - }, - "required": [ - "used", - "size", - "usage" - ], - "additionalProperties": false - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "invocation_id": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "host_status": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "text": { - "type": "string" - }, - "args": { - "type": "string" - }, - "result": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/StreamEvent", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "StreamEvent", - "additionalProperties": false -} diff --git a/packages/protocol/schema/SubmitPayload.json b/packages/protocol/schema/SubmitPayload.json deleted file mode 100644 index 46bce86c5..000000000 --- a/packages/protocol/schema/SubmitPayload.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "type": "object", - "properties": { - "design_context": { - "type": [ - "null", - "object" - ], - "properties": { - "context_attachment_id": { - "type": "string" - }, - "screenshot_attachment_id": { - "type": "string" - }, - "elements": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "label": { - "type": "string" - }, - "selector": { - "type": "string" - } - }, - "required": [ - "label" - ], - "additionalProperties": false - } - }, - "element_count": { - "type": "integer" - }, - "page_url": { - "type": "string" - }, - "page_title": { - "type": "string" - } - }, - "required": [ - "context_attachment_id", - "elements", - "element_count" - ], - "additionalProperties": false - }, - "text": { - "type": "string" - }, - "parts": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "text": { - "type": "string" - }, - "image_url": { - "type": [ - "null", - "object" - ], - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false - }, - "w": { - "type": "integer" - }, - "h": { - "type": "integer" - } - }, - "required": [ - "type" - ], - "additionalProperties": false - } - }, - "attachments": { - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": [ - "image", - "text" - ] - }, - "content": { - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "name": { - "type": "string" - } - }, - "required": [ - "kind", - "content" - ], - "additionalProperties": false - } - } - }, - "$id": "https://whip.dev/protocol/v6/SubmitPayload", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SubmitPayload", - "required": [ - "text" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SubscribeParams.json b/packages/protocol/schema/SubscribeParams.json deleted file mode 100644 index 16126132a..000000000 --- a/packages/protocol/schema/SubscribeParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "subscription_id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/SubscribeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SubscribeParams", - "required": [ - "root_id", - "subscription_id", - "cursor" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SubscribeResult.json b/packages/protocol/schema/SubscribeResult.json deleted file mode 100644 index 53c420755..000000000 --- a/packages/protocol/schema/SubscribeResult.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "subscription_id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/SubscribeResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SubscribeResult", - "required": [ - "subscription_id", - "cursor" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/SubscriptionFailure.json b/packages/protocol/schema/SubscriptionFailure.json deleted file mode 100644 index a5cbf6294..000000000 --- a/packages/protocol/schema/SubscriptionFailure.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "type": "object", - "properties": { - "subscription_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "error": { - "type": [ - "null", - "object" - ], - "properties": { - "data": { - "type": [ - "null", - "object" - ], - "properties": { - "kind": { - "type": "string" - } - }, - "required": [ - "kind" - ], - "additionalProperties": false - }, - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "required": [ - "code", - "message" - ], - "additionalProperties": false - } - }, - "$id": "https://whip.dev/protocol/v6/SubscriptionFailure", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "SubscriptionFailure", - "required": [ - "subscription_id", - "root_id", - "error" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalAttachParams.json b/packages/protocol/schema/TerminalAttachParams.json deleted file mode 100644 index 7f5bcc278..000000000 --- a/packages/protocol/schema/TerminalAttachParams.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalAttachParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalAttachParams", - "required": [ - "id", - "cursor" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalAttachResult.json b/packages/protocol/schema/TerminalAttachResult.json deleted file mode 100644 index 91b191b98..000000000 --- a/packages/protocol/schema/TerminalAttachResult.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "type": "object", - "properties": { - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "cwd": { - "type": "string" - }, - "cols": { - "type": "integer" - }, - "rows": { - "type": "integer" - }, - "exited": { - "type": "boolean" - }, - "exit_code": { - "type": "integer" - }, - "signal": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalAttachResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalAttachResult", - "required": [ - "cursor", - "cwd", - "cols", - "rows", - "exited" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalDetachedParams.json b/packages/protocol/schema/TerminalDetachedParams.json deleted file mode 100644 index 8e4c02c9e..000000000 --- a/packages/protocol/schema/TerminalDetachedParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalDetachedParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalDetachedParams", - "required": [ - "id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalExitedParams.json b/packages/protocol/schema/TerminalExitedParams.json deleted file mode 100644 index 3086b05da..000000000 --- a/packages/protocol/schema/TerminalExitedParams.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "exit_code": { - "type": "integer" - }, - "signal": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalExitedParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalExitedParams", - "required": [ - "id", - "exit_code" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalIDParams.json b/packages/protocol/schema/TerminalIDParams.json deleted file mode 100644 index 53b9ff447..000000000 --- a/packages/protocol/schema/TerminalIDParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalIDParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalIDParams", - "required": [ - "id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalInputParams.json b/packages/protocol/schema/TerminalInputParams.json deleted file mode 100644 index e442f2129..000000000 --- a/packages/protocol/schema/TerminalInputParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "bytes": { - "type": [ - "string", - "null" - ], - "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", - "contentEncoding": "base64" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalInputParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalInputParams", - "required": [ - "id", - "bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalOpenParams.json b/packages/protocol/schema/TerminalOpenParams.json deleted file mode 100644 index 1838c3bee..000000000 --- a/packages/protocol/schema/TerminalOpenParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "cwd": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "cols": { - "type": "integer" - }, - "rows": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalOpenParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalOpenParams", - "required": [ - "cols", - "rows" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalOpenResult.json b/packages/protocol/schema/TerminalOpenResult.json deleted file mode 100644 index 560c480b2..000000000 --- a/packages/protocol/schema/TerminalOpenResult.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "shell": { - "type": "string" - }, - "cwd": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalOpenResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalOpenResult", - "required": [ - "id", - "shell", - "cwd" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalOutputParams.json b/packages/protocol/schema/TerminalOutputParams.json deleted file mode 100644 index 264eb0b05..000000000 --- a/packages/protocol/schema/TerminalOutputParams.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "cursor": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "bytes": { - "type": [ - "string", - "null" - ], - "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", - "contentEncoding": "base64" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalOutputParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalOutputParams", - "required": [ - "id", - "cursor", - "bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalResizeParams.json b/packages/protocol/schema/TerminalResizeParams.json deleted file mode 100644 index 57303d75f..000000000 --- a/packages/protocol/schema/TerminalResizeParams.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "cols": { - "type": "integer" - }, - "rows": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalResizeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalResizeParams", - "required": [ - "id", - "cols", - "rows" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TerminalWriteParams.json b/packages/protocol/schema/TerminalWriteParams.json deleted file mode 100644 index 651c6bd04..000000000 --- a/packages/protocol/schema/TerminalWriteParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "bytes": { - "type": [ - "string", - "null" - ], - "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", - "contentEncoding": "base64" - } - }, - "$id": "https://whip.dev/protocol/v6/TerminalWriteParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TerminalWriteParams", - "required": [ - "id", - "bytes" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TextParams.json b/packages/protocol/schema/TextParams.json deleted file mode 100644 index 99c97dfc7..000000000 --- a/packages/protocol/schema/TextParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TextParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TextParams", - "required": [ - "text" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TextResult.json b/packages/protocol/schema/TextResult.json deleted file mode 100644 index eb16d7124..000000000 --- a/packages/protocol/schema/TextResult.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "output": true - }, - "$id": "https://whip.dev/protocol/v6/TextResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TextResult", - "required": [ - "text" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TitleParams.json b/packages/protocol/schema/TitleParams.json deleted file mode 100644 index 794120943..000000000 --- a/packages/protocol/schema/TitleParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "title": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TitleParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TitleParams", - "required": [ - "title" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TitleResult.json b/packages/protocol/schema/TitleResult.json deleted file mode 100644 index 970a822f7..000000000 --- a/packages/protocol/schema/TitleResult.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "title": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TitleResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TitleResult", - "required": [ - "title" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolCallParams.json b/packages/protocol/schema/ToolCallParams.json deleted file mode 100644 index ce7236fed..000000000 --- a/packages/protocol/schema/ToolCallParams.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "type": "object", - "properties": { - "tool": { - "type": "string" - }, - "arguments": true - }, - "$id": "https://whip.dev/protocol/v6/ToolCallParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolCallParams", - "required": [ - "tool", - "arguments" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolCancelParams.json b/packages/protocol/schema/ToolCancelParams.json deleted file mode 100644 index 0b27658f4..000000000 --- a/packages/protocol/schema/ToolCancelParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "reason": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ToolCancelParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolCancelParams", - "required": [ - "invocation_id", - "generation", - "reason" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolConfigureParams.json b/packages/protocol/schema/ToolConfigureParams.json deleted file mode 100644 index 219a76e6c..000000000 --- a/packages/protocol/schema/ToolConfigureParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "deny_permissions": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/ToolConfigureParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolConfigureParams", - "required": [ - "deny_permissions" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolInvokeParams.json b/packages/protocol/schema/ToolInvokeParams.json deleted file mode 100644 index 7c1e82f30..000000000 --- a/packages/protocol/schema/ToolInvokeParams.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "definition": { - "type": "string" - }, - "revision": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "turn_id": { - "type": "string" - }, - "tool": { - "type": "string" - }, - "input": true, - "deadline_millis": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - } - }, - "$id": "https://whip.dev/protocol/v6/ToolInvokeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolInvokeParams", - "required": [ - "invocation_id", - "definition", - "revision", - "generation", - "root_id", - "agent_id", - "turn_id", - "tool", - "input", - "deadline_millis" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolProgressParams.json b/packages/protocol/schema/ToolProgressParams.json deleted file mode 100644 index 33337af28..000000000 --- a/packages/protocol/schema/ToolProgressParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "text": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ToolProgressParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolProgressParams", - "required": [ - "invocation_id", - "generation", - "text" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolResultParams.json b/packages/protocol/schema/ToolResultParams.json deleted file mode 100644 index bdda997d6..000000000 --- a/packages/protocol/schema/ToolResultParams.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "type": "object", - "properties": { - "invocation_id": { - "type": "string" - }, - "generation": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "output": true, - "error": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/ToolResultParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolResultParams", - "required": [ - "invocation_id", - "generation" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/ToolSchemaResult.json b/packages/protocol/schema/ToolSchemaResult.json deleted file mode 100644 index 8c2f76202..000000000 --- a/packages/protocol/schema/ToolSchemaResult.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": true - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - }, - "required": [ - "type", - "function" - ], - "additionalProperties": false - }, - "$id": "https://whip.dev/protocol/v6/ToolSchemaResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "ToolSchemaResult" -} diff --git a/packages/protocol/schema/TraceExportParams.json b/packages/protocol/schema/TraceExportParams.json deleted file mode 100644 index 3892441e3..000000000 --- a/packages/protocol/schema/TraceExportParams.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "trace_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/TraceExportParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TraceExportParams", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TraceExportResult.json b/packages/protocol/schema/TraceExportResult.json deleted file mode 100644 index 2ccb915af..000000000 --- a/packages/protocol/schema/TraceExportResult.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "type": "object", - "properties": { - "content": { - "type": "object", - "properties": { - "reference_id": { - "type": "string" - }, - "digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "required": [ - "reference_id", - "digest", - "size" - ], - "additionalProperties": false - }, - "spans": { - "type": "integer" - }, - "traces": { - "type": "integer" - } - }, - "$id": "https://whip.dev/protocol/v6/TraceExportResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TraceExportResult", - "required": [ - "content", - "spans", - "traces" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/TracePageParams.json b/packages/protocol/schema/TracePageParams.json deleted file mode 100644 index 6c409dc14..000000000 --- a/packages/protocol/schema/TracePageParams.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "object", - "properties": { - "root_id": { - "type": "string" - }, - "trace_id": { - "type": "string" - }, - "after_seq": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "limit": { - "type": "integer" - }, - "roots_only": { - "type": "boolean" - } - }, - "$id": "https://whip.dev/protocol/v6/TracePageParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "TracePageParams", - "required": [ - "root_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/UnsubscribeParams.json b/packages/protocol/schema/UnsubscribeParams.json deleted file mode 100644 index c31e16ab5..000000000 --- a/packages/protocol/schema/UnsubscribeParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "subscription_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/UnsubscribeParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "UnsubscribeParams", - "required": [ - "subscription_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/UploadBeginParams.json b/packages/protocol/schema/UploadBeginParams.json deleted file mode 100644 index 9f0c44d16..000000000 --- a/packages/protocol/schema/UploadBeginParams.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "type": "object", - "properties": { - "upload_id": { - "type": "string" - }, - "root_id": { - "type": "string" - }, - "agent_id": { - "type": "string" - }, - "expected_digest": { - "type": "string" - }, - "size": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "media_type": { - "type": "string" - }, - "source": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/UploadBeginParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "UploadBeginParams", - "required": [ - "upload_id", - "root_id", - "expected_digest", - "size" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/UploadChunkParams.json b/packages/protocol/schema/UploadChunkParams.json deleted file mode 100644 index 0e8627046..000000000 --- a/packages/protocol/schema/UploadChunkParams.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "type": "object", - "properties": { - "upload_id": { - "type": "string" - }, - "offset": { - "type": "string", - "pattern": "^-?(0|[1-9][0-9]*)$", - "format": "int64" - }, - "data": { - "type": [ - "string", - "null" - ], - "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$", - "contentEncoding": "base64" - } - }, - "$id": "https://whip.dev/protocol/v6/UploadChunkParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "UploadChunkParams", - "required": [ - "upload_id", - "offset", - "data" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/UploadFinishParams.json b/packages/protocol/schema/UploadFinishParams.json deleted file mode 100644 index d8228a4b3..000000000 --- a/packages/protocol/schema/UploadFinishParams.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "type": "object", - "properties": { - "upload_id": { - "type": "string" - } - }, - "$id": "https://whip.dev/protocol/v6/UploadFinishParams", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "UploadFinishParams", - "required": [ - "upload_id" - ], - "additionalProperties": false -} diff --git a/packages/protocol/schema/UserHistoryResult.json b/packages/protocol/schema/UserHistoryResult.json deleted file mode 100644 index 0c80d9d4b..000000000 --- a/packages/protocol/schema/UserHistoryResult.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": [ - "null", - "array" - ], - "items": { - "type": "string" - }, - "$id": "https://whip.dev/protocol/v6/UserHistoryResult", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "UserHistoryResult" -} diff --git a/packages/protocol/schema/fixtures.json b/packages/protocol/schema/fixtures.json deleted file mode 100644 index 7341206c0..000000000 --- a/packages/protocol/schema/fixtures.json +++ /dev/null @@ -1,1562 +0,0 @@ -[ - { - "type": "InitializeParams", - "value": { - "protocol_major": 6, - "build_id": "fixture", - "client_kind": "human", - "client_id": "browser-fixture" - } - }, - { - "type": "HostSkillCompletionParams", - "value": { - "scope": "global", - "prefix": "", - "limit": 1024 - } - }, - { - "type": "SubscribeParams", - "value": { - "root_id": "root-fixture", - "subscription_id": "view-fixture", - "cursor": "9007199254740993" - } - }, - { - "type": "ContentHandle", - "value": { - "reference_id": "ref-fixture", - "digest": "0000000000000000000000000000000000000000000000000000000000000000", - "size": "9007199254740993" - } - }, - { - "type": "BrowserCommandResultParams", - "value": { - "command_id": "", - "root_id": "", - "provider_epoch": "", - "attachment_generation": "", - "document_revision": "" - } - }, - { - "type": "Accepted", - "value": { - "accepted": false - } - }, - { - "type": "BrowserInventoryResultParams", - "value": { - "request_id": "", - "root_id": "", - "provider_epoch": "", - "tabs": [] - } - }, - { - "type": "BrowserProviderBindParams", - "value": { - "root_id": "", - "version": 0, - "desktop_id": "", - "window_id": "", - "offer_revision": "", - "create_profile_id": "", - "offered_tabs": [], - "offered_preview_hosts": [] - } - }, - { - "type": "BrowserProviderBindResult", - "value": { - "version": 0, - "provider_id": "", - "provider_epoch": "" - } - }, - { - "type": "BrowserProviderEventParams", - "value": { - "root_id": "", - "provider_epoch": "", - "tab_id": "", - "tab_generation": "", - "attachment_id": "", - "attachment_generation": "", - "sequence": "0", - "document_revision": "", - "kind": "" - } - }, - { - "type": "BrowserProviderUnbindParams", - "value": { - "root_id": "", - "provider_epoch": "" - } - }, - { - "type": "CommandStatusParams", - "value": { - "command_id": "" - } - }, - { - "type": "CommandResult", - "value": { - "operation": "", - "command_id": "", - "ingress_seq": "0", - "status": "" - } - }, - { - "type": "CommandParams", - "value": { - "command_id": "", - "scope": "", - "operation": "" - } - }, - { - "type": "Empty", - "value": {} - }, - { - "type": "RuntimeConfiguration", - "value": { - "default_execution_engine": "", - "import_claude": false, - "import_codex": false, - "mcp_import_offered": false, - "brand_icons": false, - "revision": "", - "default_model": "", - "default_provider": "", - "default_effort": "", - "compact_model": "", - "compact_provider": "", - "compact_percent": 0, - "goal_max_rounds": 0, - "max_retries": 0 - } - }, - { - "type": "ConfigurationUpdate", - "value": { - "revision": "" - } - }, - { - "type": "ContentReadParams", - "value": { - "root_id": "", - "reference_id": "", - "offset": "0", - "limit": 0 - } - }, - { - "type": "ContentReadResult", - "value": { - "data": null, - "content": { - "reference_id": "", - "digest": "", - "size": "0" - } - } - }, - { - "type": "PingResult", - "value": { - "generation": "0", - "build_id": "" - } - }, - { - "type": "RestartParams", - "value": { - "generation": "0" - } - }, - { - "type": "DefinitionParams", - "value": { - "id": "" - } - }, - { - "type": "DefinitionRecord", - "value": { - "definition": { - "id": "", - "instructions": { - "persona": "", - "rules": "", - "project_files": [], - "skill_discovery": false, - "standing_instructions": false - }, - "modules": [], - "capabilities": [], - "model": { - "model": "", - "provider": "", - "effort": "" - }, - "compaction": { - "model": "", - "provider": "", - "threshold": 0 - }, - "mcp": { - "servers": [] - }, - "tools": [], - "output": null, - "children": {}, - "surface": { - "auto_title": false, - "goal_loop": false - }, - "hooks": null - }, - "revision": "", - "built_in": false, - "registered_by": "", - "created_at": "" - } - }, - { - "type": "DefinitionList", - "value": { - "items": [] - } - }, - { - "type": "DefinitionRegisterParams", - "value": { - "definition": { - "id": "", - "instructions": { - "persona": "", - "rules": "", - "project_files": [], - "skill_discovery": false, - "standing_instructions": false - }, - "modules": [], - "capabilities": [], - "model": { - "model": "", - "provider": "", - "effort": "" - }, - "compaction": { - "model": "", - "provider": "", - "threshold": 0 - }, - "mcp": { - "servers": [] - }, - "tools": [], - "output": null, - "children": {}, - "surface": { - "auto_title": false, - "goal_loop": false - }, - "hooks": null - } - } - }, - { - "type": "DefinitionRegisterResult", - "value": { - "id": "", - "revision": "", - "created": false - } - }, - { - "type": "ReplayParams", - "value": { - "root_id": "", - "cursor": "0" - } - }, - { - "type": "ReplayResult", - "value": { - "events": [], - "latest": "0" - } - }, - { - "type": "SubscribeResult", - "value": { - "subscription_id": "", - "cursor": "0" - } - }, - { - "type": "UnsubscribeParams", - "value": { - "subscription_id": "" - } - }, - { - "type": "ExecutorBindParams", - "value": { - "definition": "", - "revision": "", - "tools": [] - } - }, - { - "type": "ExecutorBindResult", - "value": { - "generation": "0", - "tools": [] - } - }, - { - "type": "ExecutorPendingParams", - "value": { - "definition": "", - "revision": "", - "generation": "0" - } - }, - { - "type": "ExecutorPendingResult", - "value": { - "invocations": [] - } - }, - { - "type": "GatewayStatus", - "value": { - "state": "" - } - }, - { - "type": "HistoryPageParams", - "value": { - "root_id": "", - "agent_id": "", - "through_seq": 0, - "limit": 0, - "max_bytes": 0 - } - }, - { - "type": "BoundedTranscriptPage", - "value": { - "history_revision": "0", - "through_seq": 0, - "next_seq": 0, - "has_more": false, - "messages": [] - } - }, - { - "type": "HookResultParams", - "value": { - "invocation_id": "", - "generation": "0" - } - }, - { - "type": "HostAttentionParams", - "value": { - "limit": 0, - "max_bytes": 0 - } - }, - { - "type": "HostAttentionResult", - "value": { - "items": [], - "has_more": false, - "truncated": false - } - }, - { - "type": "HostDirectoryParams", - "value": { - "limit": 0 - } - }, - { - "type": "HostDirectoryResult", - "value": { - "path": "", - "parent": "", - "entries": [], - "has_more": false, - "truncated": false - } - }, - { - "type": "HostDirectoryPickParams", - "value": {} - }, - { - "type": "HostDirectoryPickResult", - "value": { - "cancelled": false - } - }, - { - "type": "CompletionResult", - "value": { - "candidates": [], - "truncated": false - } - }, - { - "type": "EmptyParams", - "value": {} - }, - { - "type": "CatalogResult", - "value": { - "themes": [], - "errors": [], - "truncated": false - } - }, - { - "type": "HostThemeResolveParams", - "value": {} - }, - { - "type": "Resolved", - "value": { - "id": "", - "name": "", - "dark": false, - "colors": { - "background": "", - "foreground": "", - "muted": "", - "faint": "", - "primary": "", - "on_primary": "", - "accent": "", - "success": "", - "warning": "", - "error": "", - "info": "", - "link": "", - "emphasis": "", - "border": "", - "border_focus": "", - "diff_add": "", - "diff_del": "", - "panel": "", - "element": "", - "hover": "" - }, - "syntax": { - "keyword": "", - "string": "", - "number": "", - "comment": "", - "function": "", - "type": "", - "operator": "", - "punctuation": "" - }, - "markdown": { - "heading": "", - "strong": "", - "code": "", - "quote": "" - }, - "code": { - "foreground": "", - "background": "", - "tokens": {} - } - } - }, - { - "type": "InitializeResult", - "value": { - "execution_engines": [], - "default_execution_engine": "", - "operations": [], - "limits": { - "frame_bytes": 0, - "connections": 0, - "in_flight_requests": 0, - "outbound_messages": 0, - "outbound_bytes": "0", - "root_subscriptions": 0, - "content_chunk_bytes": 0, - "upload_bytes": "0" - }, - "negotiated_capabilities": [], - "protocol_minor": 0, - "runtime_id": "", - "connection_id": "", - "host_platform": "", - "host_architecture": "", - "protocol_major": 0, - "build_id": "", - "generation": "0", - "capabilities": [] - } - }, - { - "type": "MailboxPageParams", - "value": { - "root_id": "", - "agent_id": "", - "limit": 0, - "max_bytes": 0 - } - }, - { - "type": "MailboxPage", - "value": { - "revision": "0", - "items": [], - "has_more": false - } - }, - { - "type": "MailboxReadParams", - "value": { - "root_id": "", - "agent_id": "", - "id": "" - } - }, - { - "type": "MailboxInspection", - "value": { - "id": "", - "revision": "0", - "sender": "", - "recipient": "", - "kind": "", - "delivery": "", - "subject": "", - "excerpt": "", - "body": { - "reference_id": "", - "digest": "", - "size": "0", - "media_type": "", - "source": "" - }, - "status": "", - "available_at": "0001-01-01T00:00:00Z", - "created_at": "0001-01-01T00:00:00Z", - "delivered_at": "0001-01-01T00:00:00Z", - "done_at": "0001-01-01T00:00:00Z" - } - }, - { - "type": "MCPBrandIconsParams", - "value": { - "keys": [] - } - }, - { - "type": "MCPBrandIconsResult", - "value": { - "icons": {} - } - }, - { - "type": "MCPImportApplyParams", - "value": { - "names": [] - } - }, - { - "type": "MCPImportApplyResult", - "value": { - "imported": [] - } - }, - { - "type": "MCPImportCandidatesParams", - "value": {} - }, - { - "type": "MCPImportCandidatesResult", - "value": { - "candidates": [], - "offered": false, - "config_path": "" - } - }, - { - "type": "QueryParams", - "value": { - "operation": "" - } - }, - { - "type": "QueryResult", - "value": {} - }, - { - "type": "PermissionDecisionParams", - "value": { - "decision": { - "command_id": "", - "root_id": "", - "permission_id": "", - "allow": false - } - } - }, - { - "type": "PermissionDecisionResult", - "value": { - "operation_id": "", - "lease_id": "" - } - }, - { - "type": "ProviderCreateParams", - "value": { - "revision": "", - "provider": "", - "definition": { - "name": "", - "base_url": "", - "api": "" - }, - "credential": { - "mode": "" - } - } - }, - { - "type": "ProviderConfiguration", - "value": { - "revision": "", - "provider": "", - "definition": { - "name": "", - "base_url": "", - "api": "" - }, - "custom": false, - "credential": { - "mode": "", - "configured": false - }, - "models": [], - "removal_blockers": [] - } - }, - { - "type": "ProviderDisconnectParams", - "value": { - "provider": "", - "revision": "" - } - }, - { - "type": "ProviderStatus", - "value": { - "provider": "", - "configured": false, - "key_source": "", - "warnings": [] - } - }, - { - "type": "ProviderListParams", - "value": {} - }, - { - "type": "ProviderList", - "value": { - "revision": "", - "providers": [] - } - }, - { - "type": "ProviderNameParams", - "value": { - "provider": "" - } - }, - { - "type": "ProviderKeySetup", - "value": { - "revision": "", - "provider": "", - "environment": false - } - }, - { - "type": "ProviderLoginBeginParams", - "value": {} - }, - { - "type": "ProviderLoginStatus", - "value": { - "flow_id": "", - "state": "", - "teams": [], - "projects": [], - "expires_at": "0001-01-01T00:00:00Z" - } - }, - { - "type": "ProviderLoginParams", - "value": { - "flow_id": "" - } - }, - { - "type": "ProviderLoginList", - "value": { - "flows": [] - } - }, - { - "type": "ProviderLoginCreateParams", - "value": { - "flow_id": "", - "name": "" - } - }, - { - "type": "ProviderLoginProjectParams", - "value": { - "flow_id": "", - "project_id": "" - } - }, - { - "type": "ProviderLoginTeamParams", - "value": { - "flow_id": "", - "team_id": "" - } - }, - { - "type": "ProviderRemoveParams", - "value": { - "revision": "", - "provider": "" - } - }, - { - "type": "ProviderRemoveResult", - "value": { - "revision": "" - } - }, - { - "type": "ProviderUpdateParams", - "value": { - "revision": "", - "provider": "" - } - }, - { - "type": "ProviderValidateParams", - "value": { - "name": "", - "base_url": "", - "key": "" - } - }, - { - "type": "ProviderValidateResult", - "value": { - "models": [] - } - }, - { - "type": "RootCollectionParams", - "value": { - "root_id": "", - "collection": "", - "limit": 0, - "max_bytes": 0 - } - }, - { - "type": "RootCollectionPage", - "value": { - "root_id": "", - "collection": "", - "revision": "0", - "event_cursor": "0", - "items": [], - "has_more": false - } - }, - { - "type": "SnapshotParams", - "value": { - "root_id": "" - } - }, - { - "type": "RootSnapshot", - "value": { - "active_turns": {}, - "message_seqs": [], - "history_revision": "0", - "root_id": "", - "cursor": "0", - "meta": { - "execution_engine": "", - "definition": "", - "definition_revision": "", - "id": "", - "kind": "", - "title": "", - "model": "", - "provider": "", - "cwd": "", - "goal": "", - "forked_from": "", - "fork_seq": 0, - "tags": [], - "archived": false, - "pinned": false, - "effort": "", - "usage_in": 0, - "usage_cached": 0, - "usage_out": 0, - "updated_at": "0001-01-01T00:00:00Z" - }, - "messages": [], - "presentation": [], - "agent_presentations": {}, - "agents": [], - "inbox": [], - "blackboard": [], - "budgets": [], - "accounting": { - "root_id": "", - "agent_id": "", - "scope": "", - "revision": "0", - "reported_cost_micros": "0", - "estimated_cost_micros": "0", - "reported_cost_calls": "0", - "estimated_cost_calls": "0", - "unknown_cost_calls": "0", - "reported_calls": "0", - "estimated_calls": "0", - "pending_calls": "0" - }, - "capabilities": [], - "schedules": [], - "permissions": [], - "questions": [] - } - }, - { - "type": "RootParams", - "value": { - "root_id": "" - } - }, - { - "type": "SessionMetadata", - "value": { - "root_id": "", - "title": "", - "cwd": "", - "history_revision": "0", - "archived": false - } - }, - { - "type": "SessionCatalogParams", - "value": { - "limit": 0, - "max_bytes": 0 - } - }, - { - "type": "SessionCatalogPage", - "value": { - "revision": "0", - "items": [], - "has_more": false - } - }, - { - "type": "CatalogRevision", - "value": { - "revision": "0" - } - }, - { - "type": "SessionSummariesParams", - "value": { - "root_ids": [] - } - }, - { - "type": "SessionSummariesResult", - "value": { - "items": [] - } - }, - { - "type": "TerminalAttachParams", - "value": { - "id": "", - "cursor": "0" - } - }, - { - "type": "TerminalAttachResult", - "value": { - "cursor": "0", - "cwd": "", - "cols": 0, - "rows": 0, - "exited": false - } - }, - { - "type": "TerminalIDParams", - "value": { - "id": "" - } - }, - { - "type": "TerminalOpenParams", - "value": { - "cols": 0, - "rows": 0 - } - }, - { - "type": "TerminalOpenResult", - "value": { - "id": "", - "shell": "", - "cwd": "" - } - }, - { - "type": "TerminalResizeParams", - "value": { - "id": "", - "cols": 0, - "rows": 0 - } - }, - { - "type": "TerminalWriteParams", - "value": { - "id": "", - "bytes": null - } - }, - { - "type": "ToolProgressParams", - "value": { - "invocation_id": "", - "generation": "0", - "text": "" - } - }, - { - "type": "ToolResultParams", - "value": { - "invocation_id": "", - "generation": "0" - } - }, - { - "type": "TraceExportParams", - "value": { - "root_id": "" - } - }, - { - "type": "TraceExportResult", - "value": { - "content": { - "reference_id": "", - "digest": "", - "size": "0" - }, - "spans": 0, - "traces": 0 - } - }, - { - "type": "TracePageParams", - "value": { - "root_id": "" - } - }, - { - "type": "SpanPage", - "value": { - "root_id": "", - "spans": [], - "next_seq": "0", - "has_more": false, - "server_time_ns": "0" - } - }, - { - "type": "UploadBeginParams", - "value": { - "upload_id": "", - "root_id": "", - "expected_digest": "", - "size": "0" - } - }, - { - "type": "UploadChunkParams", - "value": { - "upload_id": "", - "offset": "0", - "data": null - } - }, - { - "type": "UploadFinishParams", - "value": { - "upload_id": "" - } - }, - { - "type": "CompletionParams", - "value": { - "root_id": "", - "kind": "", - "prefix": "", - "limit": 0 - } - }, - { - "type": "IDParams", - "value": { - "id": "" - } - }, - { - "type": "AgentInputParams", - "value": { - "id": "", - "text": "" - } - }, - { - "type": "AgentSubmitResult", - "value": { - "agent_id": "", - "inbox_seq": "0", - "status": "" - } - }, - { - "type": "AgentTranscriptResult", - "value": { - "accounting": { - "root_id": "", - "agent_id": "", - "scope": "", - "revision": "0", - "reported_cost_micros": "0", - "estimated_cost_micros": "0", - "reported_cost_calls": "0", - "estimated_cost_calls": "0", - "unknown_cost_calls": "0", - "reported_calls": "0", - "estimated_calls": "0", - "pending_calls": "0" - }, - "cursor": "0", - "agent": { - "execution_engine": "", - "id": "", - "root_id": "", - "parent_id": "", - "name": "", - "model": "", - "provider": "", - "effort": "", - "cwd": "", - "report": "", - "status": "", - "pending_mail": 0, - "lifecycle_phase": "", - "blocking_reason": "", - "terminal_cause": "", - "allowed_controls": [] - }, - "page": { - "history_revision": "0", - "through_seq": 0, - "next_seq": 0, - "has_more": false, - "messages": [] - } - } - }, - { - "type": "AgentCancelParams", - "value": { - "id": "", - "turn_id": "" - } - }, - { - "type": "AgentListResult", - "value": [] - }, - { - "type": "BrowserDriverParams", - "value": { - "driver": "" - } - }, - { - "type": "BrowserStatusResult", - "value": { - "enabled": false - } - }, - { - "type": "BudgetCapParams", - "value": { - "id": "", - "kind": "", - "limit": "0" - } - }, - { - "type": "BudgetState", - "value": { - "kind": "", - "limit": null, - "used": "0", - "reserved": "0", - "remaining": null, - "uncertain": "0", - "incomplete": false - } - }, - { - "type": "CancelParams", - "value": {} - }, - { - "type": "CapabilityRecord", - "value": { - "id": "", - "root_id": "", - "agent_id": "", - "issuer_agent_id": "", - "operations": [], - "scopes": [], - "mcp": [], - "mcp_all": false, - "generation": "0", - "status": "", - "expires_at": "0001-01-01T00:00:00Z", - "created_at": "0001-01-01T00:00:00Z", - "updated_at": "0001-01-01T00:00:00Z" - } - }, - { - "type": "CompactionParams", - "value": {} - }, - { - "type": "CompactionSettingsResult", - "value": { - "builtin_default": false - } - }, - { - "type": "ComputerAppParams", - "value": { - "app": "" - } - }, - { - "type": "ComputerStatusResult", - "value": { - "enabled": false, - "default_deny": false, - "allowed": [], - "denied": [], - "session_allowed": [], - "session_denied": [] - } - }, - { - "type": "ContextAuditResult", - "value": { - "working_directory": "", - "rows": [] - } - }, - { - "type": "CheckpointParams", - "value": {} - }, - { - "type": "RestartNotice", - "value": { - "generation": "0", - "cursors": {} - } - }, - { - "type": "GoalContextParams", - "value": {} - }, - { - "type": "GoalResult", - "value": { - "goal": "" - } - }, - { - "type": "TextParams", - "value": { - "text": "" - } - }, - { - "type": "ClearHistoryParams", - "value": {} - }, - { - "type": "CompactionResult", - "value": { - "cutoff": 0, - "usage": { - "reported": false, - "prompt_tokens": 0, - "completion_tokens": 0 - } - } - }, - { - "type": "CompactionListResult", - "value": [] - }, - { - "type": "CompactionRetryResult", - "value": { - "undone": false - } - }, - { - "type": "RewindParams", - "value": { - "expected_revision": null, - "cut": 0 - } - }, - { - "type": "RewindResult", - "value": { - "cut": 0, - "restored_files": 0 - } - }, - { - "type": "UserHistoryResult", - "value": [] - }, - { - "type": "InboxRemoveParams", - "value": { - "id": "", - "inbox_seq": "0" - } - }, - { - "type": "InboxControlResult", - "value": { - "agent_id": "", - "inbox_seq": "0", - "status": "" - } - }, - { - "type": "InboxSteerParams", - "value": { - "id": "", - "inbox_seq": "0", - "turn_id": "" - } - }, - { - "type": "LSPListResult", - "value": [] - }, - { - "type": "MCPAttachParams", - "value": { - "servers": {} - } - }, - { - "type": "MCPServerParams", - "value": { - "name": "" - } - }, - { - "type": "MCPImportParams", - "value": { - "source": "", - "enabled": false - } - }, - { - "type": "MCPImportStatusResult", - "value": { - "claude": false, - "codex": false, - "project": false, - "opencode": false - } - }, - { - "type": "MCPRefreshResult", - "value": { - "added": [], - "existing": [], - "changed": [], - "servers": [], - "blocked": [], - "source_errors": [] - } - }, - { - "type": "MCPListResult", - "value": [] - }, - { - "type": "PermissionConfigureParams", - "value": { - "external_permissions": false - } - }, - { - "type": "PermissionRulesResult", - "value": { - "rules": [], - "global": [] - } - }, - { - "type": "ProviderCatalogParams", - "value": {} - }, - { - "type": "ProviderCatalogsResult", - "value": { - "models": {}, - "providers": {}, - "catalogs": {} - } - }, - { - "type": "QuestionAnswerParams", - "value": { - "id": "", - "answer": [], - "dismissed": false - } - }, - { - "type": "RunConfigureParams", - "value": {} - }, - { - "type": "ScheduleCreateParams", - "value": { - "schedule": "", - "prompt": "" - } - }, - { - "type": "ScheduleResult", - "value": { - "schedule_id": 0 - } - }, - { - "type": "ScheduleDeleteParams", - "value": { - "schedule_id": 0 - } - }, - { - "type": "ScheduleListResult", - "value": [] - }, - { - "type": "ArchiveParams", - "value": { - "archived": false - } - }, - { - "type": "ArchiveResult", - "value": { - "archived": false - } - }, - { - "type": "CreateSessionParams", - "value": { - "kind": "", - "cwd": "", - "model": "", - "provider": "" - } - }, - { - "type": "RootIDResult", - "value": { - "root_id": "" - } - }, - { - "type": "EffortParams", - "value": { - "effort": "", - "persist_default": false - } - }, - { - "type": "EffortResult", - "value": { - "effort": "" - } - }, - { - "type": "ForkParams", - "value": { - "expected_revision": null - } - }, - { - "type": "ListParams", - "value": {} - }, - { - "type": "SessionListResult", - "value": [] - }, - { - "type": "ModelParams", - "value": { - "model": "", - "persist_default": false - } - }, - { - "type": "ModelResult", - "value": { - "model": "", - "provider": "" - } - }, - { - "type": "SessionPreviewResult", - "value": { - "root_id": "", - "user": "", - "assistant": "" - } - }, - { - "type": "TitleParams", - "value": { - "title": "" - } - }, - { - "type": "TitleResult", - "value": { - "title": "" - } - }, - { - "type": "ShellParams", - "value": { - "command": "" - } - }, - { - "type": "TextResult", - "value": { - "text": "" - } - }, - { - "type": "SubmitPayload", - "value": { - "text": "" - } - }, - { - "type": "TerminalInputParams", - "value": { - "id": "", - "bytes": null - } - }, - { - "type": "ToolCallParams", - "value": { - "tool": "", - "arguments": null - } - }, - { - "type": "ToolConfigureParams", - "value": { - "deny_permissions": false - } - }, - { - "type": "ToolSchemaResult", - "value": [] - }, - { - "type": "PathResult", - "value": { - "path": "" - } - }, - { - "type": "PathParams", - "value": { - "path": "" - } - } -] diff --git a/packages/protocol/schema/manifest.json b/packages/protocol/schema/manifest.json deleted file mode 100644 index f5a221f9f..000000000 --- a/packages/protocol/schema/manifest.json +++ /dev/null @@ -1,1280 +0,0 @@ -{ - "major": 6, - "minor": 9, - "operations": [ - { - "name": "browser.command.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserCommandResultParams", - "result_type": "Accepted" - }, - { - "name": "browser.inventory.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserInventoryResultParams", - "result_type": "Accepted" - }, - { - "name": "browser.provider.bind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderBindParams", - "result_type": "BrowserProviderBindResult" - }, - { - "name": "browser.provider.event", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderEventParams", - "result_type": "Accepted" - }, - { - "name": "browser.provider.unbind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "browser-provider", - "params_type": "BrowserProviderUnbindParams", - "result_type": "Accepted" - }, - { - "name": "command.status", - "surface": "rpc", - "execution": "query", - "permission": "client-command-namespace", - "params_type": "CommandStatusParams", - "result_type": "CommandResult" - }, - { - "name": "command.submit", - "surface": "rpc", - "execution": "command", - "permission": "operation-specific", - "params_type": "CommandParams", - "result_type": "CommandResult" - }, - { - "name": "config.get", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "RuntimeConfiguration" - }, - { - "name": "config.update", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ConfigurationUpdate", - "result_type": "RuntimeConfiguration" - }, - { - "name": "content.read", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-content-grant", - "params_type": "ContentReadParams", - "result_type": "ContentReadResult" - }, - { - "name": "daemon.ping", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "PingResult" - }, - { - "name": "daemon.restart", - "surface": "rpc", - "execution": "lifecycle", - "permission": "armed-generation", - "params_type": "RestartParams", - "result_type": "Empty" - }, - { - "name": "daemon.stop", - "surface": "rpc", - "execution": "lifecycle", - "permission": "armed-generation", - "params_type": "RestartParams", - "result_type": "Empty" - }, - { - "name": "definitions.get", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "DefinitionParams", - "result_type": "DefinitionRecord" - }, - { - "name": "definitions.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "Empty", - "result_type": "DefinitionList" - }, - { - "name": "definitions.register", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-runtime", - "params_type": "DefinitionRegisterParams", - "result_type": "DefinitionRegisterResult" - }, - { - "name": "events.replay", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "ReplayParams", - "result_type": "ReplayResult" - }, - { - "name": "events.subscribe", - "surface": "rpc", - "execution": "subscription", - "permission": "root-association", - "params_type": "SubscribeParams", - "result_type": "SubscribeResult" - }, - { - "name": "events.unsubscribe", - "surface": "rpc", - "execution": "subscription", - "permission": "connection-subscription", - "params_type": "UnsubscribeParams", - "result_type": "Empty" - }, - { - "name": "executor.bind", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-runtime", - "params_type": "ExecutorBindParams", - "result_type": "ExecutorBindResult" - }, - { - "name": "executor.pending", - "surface": "rpc", - "execution": "query", - "permission": "executor-lease", - "params_type": "ExecutorPendingParams", - "result_type": "ExecutorPendingResult" - }, - { - "name": "gateway.status", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "Empty", - "result_type": "GatewayStatus" - }, - { - "name": "history.page", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "HistoryPageParams", - "result_type": "BoundedTranscriptPage" - }, - { - "name": "hook.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "HookResultParams", - "result_type": "Accepted" - }, - { - "name": "host.attention", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostAttentionParams", - "result_type": "HostAttentionResult" - }, - { - "name": "host.directories.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostDirectoryParams", - "result_type": "HostDirectoryResult" - }, - { - "name": "host.directory.pick", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostDirectoryPickParams", - "result_type": "HostDirectoryPickResult" - }, - { - "name": "host.skills.complete", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostSkillCompletionParams", - "result_type": "CompletionResult" - }, - { - "name": "host.themes.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "EmptyParams", - "result_type": "CatalogResult" - }, - { - "name": "host.themes.resolve", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "HostThemeResolveParams", - "result_type": "Resolved" - }, - { - "name": "initialize", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "InitializeParams", - "result_type": "InitializeResult" - }, - { - "name": "mailbox.list", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "MailboxPageParams", - "result_type": "MailboxPage" - }, - { - "name": "mailbox.read", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "MailboxReadParams", - "result_type": "MailboxInspection" - }, - { - "name": "mcp.brand.icons", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "MCPBrandIconsParams", - "result_type": "MCPBrandIconsResult" - }, - { - "name": "mcp.import.apply", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "MCPImportApplyParams", - "result_type": "MCPImportApplyResult" - }, - { - "name": "mcp.import.candidates", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "MCPImportCandidatesParams", - "result_type": "MCPImportCandidatesResult" - }, - { - "name": "operation.invoke", - "surface": "rpc", - "execution": "ephemeral", - "permission": "operation-specific", - "sensitive": true, - "params_type": "QueryParams", - "result_type": "QueryResult" - }, - { - "name": "permission.decide", - "surface": "rpc", - "execution": "ephemeral", - "permission": "trusted-client-decision", - "params_type": "PermissionDecisionParams", - "result_type": "PermissionDecisionResult" - }, - { - "name": "provider.create", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderCreateParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.disconnect", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ProviderDisconnectParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.discover", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderListParams", - "result_type": "ProviderList" - }, - { - "name": "provider.get", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.key.rotate", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "sensitive": true, - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.key.set", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderKeySetup", - "result_type": "RuntimeConfiguration" - }, - { - "name": "provider.list", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderListParams", - "result_type": "ProviderList" - }, - { - "name": "provider.login.begin", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginBeginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.cancel", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.list", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "Empty", - "result_type": "ProviderLoginList" - }, - { - "name": "provider.login.project.create", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginCreateParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.project.select", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginProjectParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.status", - "surface": "rpc", - "execution": "query", - "permission": "none", - "params_type": "ProviderLoginParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.login.team.select", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderLoginTeamParams", - "result_type": "ProviderLoginStatus" - }, - { - "name": "provider.logout", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.remove", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "params_type": "ProviderRemoveParams", - "result_type": "ProviderRemoveResult" - }, - { - "name": "provider.status", - "surface": "rpc", - "execution": "query", - "permission": "host-configuration", - "params_type": "ProviderNameParams", - "result_type": "ProviderStatus" - }, - { - "name": "provider.update", - "surface": "rpc", - "execution": "ephemeral", - "permission": "configuration-revision", - "sensitive": true, - "params_type": "ProviderUpdateParams", - "result_type": "ProviderConfiguration" - }, - { - "name": "provider.validate", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-configuration", - "sensitive": true, - "params_type": "ProviderValidateParams", - "result_type": "ProviderValidateResult" - }, - { - "name": "query", - "surface": "rpc", - "execution": "query", - "permission": "operation-specific", - "params_type": "QueryParams", - "result_type": "QueryResult" - }, - { - "name": "root.collection", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "RootCollectionParams", - "result_type": "RootCollectionPage" - }, - { - "name": "root.snapshot", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "SnapshotParams", - "result_type": "RootSnapshot" - }, - { - "name": "sessions.get", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "RootParams", - "result_type": "SessionMetadata" - }, - { - "name": "sessions.list", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "SessionCatalogParams", - "result_type": "SessionCatalogPage" - }, - { - "name": "sessions.revision", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "EmptyParams", - "result_type": "CatalogRevision" - }, - { - "name": "sessions.summaries", - "surface": "rpc", - "execution": "query", - "permission": "host-runtime", - "params_type": "SessionSummariesParams", - "result_type": "SessionSummariesResult" - }, - { - "name": "terminal.attach", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalAttachParams", - "result_type": "TerminalAttachResult" - }, - { - "name": "terminal.close", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalIDParams", - "result_type": "Accepted" - }, - { - "name": "terminal.open", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalOpenParams", - "result_type": "TerminalOpenResult" - }, - { - "name": "terminal.resize", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "params_type": "TerminalResizeParams", - "result_type": "Accepted" - }, - { - "name": "terminal.write", - "surface": "rpc", - "execution": "ephemeral", - "permission": "host-terminal", - "sensitive": true, - "params_type": "TerminalWriteParams", - "result_type": "Accepted" - }, - { - "name": "tool.progress", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "ToolProgressParams", - "result_type": "Accepted" - }, - { - "name": "tool.result", - "surface": "rpc", - "execution": "ephemeral", - "permission": "executor-lease", - "params_type": "ToolResultParams", - "result_type": "Accepted" - }, - { - "name": "trace.export", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "TraceExportParams", - "result_type": "TraceExportResult" - }, - { - "name": "trace.page", - "surface": "rpc", - "execution": "query", - "permission": "root-association", - "params_type": "TracePageParams", - "result_type": "SpanPage" - }, - { - "name": "upload.begin", - "surface": "rpc", - "execution": "ephemeral", - "permission": "content-grant", - "params_type": "UploadBeginParams", - "result_type": "Accepted" - }, - { - "name": "upload.chunk", - "surface": "rpc", - "execution": "ephemeral", - "permission": "connection-upload", - "params_type": "UploadChunkParams", - "result_type": "Accepted" - }, - { - "name": "upload.finish", - "surface": "rpc", - "execution": "ephemeral", - "permission": "content-grant", - "params_type": "UploadFinishParams", - "result_type": "ContentHandle" - }, - { - "name": "workspace.complete", - "surface": "rpc", - "execution": "query", - "permission": "root-agent-association", - "params_type": "CompletionParams", - "result_type": "CompletionResult" - }, - { - "name": "agent.control", - "surface": "runtime", - "execution": "command", - "permission": "agent-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "agent.delete", - "surface": "runtime", - "execution": "command", - "permission": "agent-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "agent.submit", - "surface": "runtime", - "execution": "command", - "permission": "agent-admission", - "params_type": "AgentInputParams", - "result_type": "AgentSubmitResult" - }, - { - "name": "agent.transcript", - "surface": "runtime", - "execution": "query", - "permission": "human-transcript-inspection", - "params_type": "IDParams", - "result_type": "AgentTranscriptResult" - }, - { - "name": "agent.turn.cancel", - "surface": "runtime", - "execution": "command", - "permission": "target-turn", - "params_type": "AgentCancelParams", - "result_type": "Empty" - }, - { - "name": "agents.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "AgentListResult" - }, - { - "name": "browser.set_driver", - "surface": "runtime", - "execution": "command", - "permission": "host-configuration", - "params_type": "BrowserDriverParams", - "result_type": "BrowserStatusResult" - }, - { - "name": "browser.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "BrowserStatusResult" - }, - { - "name": "budget.cap", - "surface": "runtime", - "execution": "command", - "permission": "budget-authority", - "params_type": "BudgetCapParams", - "result_type": "BudgetState" - }, - { - "name": "cancel", - "surface": "runtime", - "execution": "command", - "permission": "target-turn", - "params_type": "CancelParams", - "result_type": "Empty" - }, - { - "name": "capability.revoke", - "surface": "runtime", - "execution": "command", - "permission": "capability-authority", - "params_type": "IDParams", - "result_type": "CapabilityRecord" - }, - { - "name": "compaction.configure", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "CompactionParams", - "result_type": "CompactionSettingsResult" - }, - { - "name": "computer.allow", - "surface": "runtime", - "execution": "command", - "permission": "human-computer-policy", - "params_type": "ComputerAppParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "computer.deny", - "surface": "runtime", - "execution": "command", - "permission": "human-computer-policy", - "params_type": "ComputerAppParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "computer.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ComputerStatusResult" - }, - { - "name": "context.audit", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ContextAuditResult" - }, - { - "name": "daemon.checkpoint", - "surface": "runtime", - "execution": "command", - "permission": "host-runtime", - "params_type": "CheckpointParams", - "result_type": "RestartNotice" - }, - { - "name": "goal.from-context", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "GoalContextParams", - "result_type": "GoalResult" - }, - { - "name": "goal.run", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "TextParams", - "result_type": "GoalResult" - }, - { - "name": "goal.set", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "TextParams", - "result_type": "GoalResult" - }, - { - "name": "history.clear", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "ClearHistoryParams", - "result_type": "Empty" - }, - { - "name": "history.compact", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "CompactionResult" - }, - { - "name": "history.compact.log", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "CompactionListResult" - }, - { - "name": "history.compact.retry", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "CompactionRetryResult" - }, - { - "name": "history.rewind", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "RewindParams", - "result_type": "RewindResult" - }, - { - "name": "history.user.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "UserHistoryResult" - }, - { - "name": "inbox.remove", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "InboxRemoveParams", - "result_type": "InboxControlResult" - }, - { - "name": "inbox.steer", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "InboxSteerParams", - "result_type": "InboxControlResult" - }, - { - "name": "lsp.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "LSPListResult" - }, - { - "name": "mcp.attach", - "surface": "runtime", - "execution": "ephemeral", - "permission": "delegated-mcp-authority", - "sensitive": true, - "params_type": "MCPAttachParams", - "result_type": "Empty" - }, - { - "name": "mcp.disable", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.enable", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.import.configure", - "surface": "runtime", - "execution": "command", - "permission": "host-configuration", - "params_type": "MCPImportParams", - "result_type": "MCPImportStatusResult" - }, - { - "name": "mcp.import.status", - "surface": "runtime", - "execution": "query", - "permission": "host-configuration", - "params_type": "EmptyParams", - "result_type": "MCPImportStatusResult" - }, - { - "name": "mcp.reconnect", - "surface": "runtime", - "execution": "command", - "permission": "delegated-mcp-authority", - "params_type": "MCPServerParams", - "result_type": "Empty" - }, - { - "name": "mcp.refresh", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "MCPRefreshResult" - }, - { - "name": "mcp.status", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "MCPListResult" - }, - { - "name": "permission.forget", - "surface": "runtime", - "execution": "command", - "permission": "rule-authority", - "params_type": "IDParams", - "result_type": "Empty" - }, - { - "name": "permission.mode", - "surface": "runtime", - "execution": "command", - "permission": "trusted-client-mode", - "params_type": "PermissionConfigureParams", - "result_type": "Empty" - }, - { - "name": "permission.rules", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "PermissionRulesResult" - }, - { - "name": "provider.catalogs", - "surface": "runtime", - "execution": "query", - "permission": "host-runtime", - "params_type": "ProviderCatalogParams", - "result_type": "ProviderCatalogsResult" - }, - { - "name": "question.answer", - "surface": "runtime", - "execution": "command", - "permission": "pending-question", - "params_type": "QuestionAnswerParams", - "result_type": "Empty" - }, - { - "name": "run.configure", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "RunConfigureParams", - "result_type": "Empty" - }, - { - "name": "schedule.create", - "surface": "runtime", - "execution": "command", - "permission": "schedule-budget", - "params_type": "ScheduleCreateParams", - "result_type": "ScheduleResult" - }, - { - "name": "schedule.delete", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ScheduleDeleteParams", - "result_type": "ScheduleResult" - }, - { - "name": "schedule.list", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ScheduleListResult" - }, - { - "name": "session.archive", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ArchiveParams", - "result_type": "ArchiveResult" - }, - { - "name": "session.create", - "surface": "runtime", - "execution": "command", - "permission": "host-runtime", - "params_type": "CreateSessionParams", - "result_type": "RootIDResult" - }, - { - "name": "session.delete", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "RootParams", - "result_type": "RootIDResult" - }, - { - "name": "session.effort", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EffortParams", - "result_type": "EffortResult" - }, - { - "name": "session.effort.get", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "EffortResult" - }, - { - "name": "session.fork", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "ForkParams", - "result_type": "RootIDResult" - }, - { - "name": "session.list", - "surface": "runtime", - "execution": "query", - "permission": "host-runtime", - "params_type": "ListParams", - "result_type": "SessionListResult" - }, - { - "name": "session.model", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "ModelParams", - "result_type": "ModelResult" - }, - { - "name": "session.model.get", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "ModelResult" - }, - { - "name": "session.open", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "IDParams", - "result_type": "RootIDResult" - }, - { - "name": "session.preview", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "IDParams", - "result_type": "SessionPreviewResult" - }, - { - "name": "session.reload", - "surface": "runtime", - "execution": "command", - "permission": "root-idle", - "params_type": "EmptyParams", - "result_type": "ModelResult" - }, - { - "name": "session.rename", - "surface": "runtime", - "execution": "command", - "permission": "root-association", - "params_type": "TitleParams", - "result_type": "TitleResult" - }, - { - "name": "shell.run", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ShellParams", - "result_type": "TextResult" - }, - { - "name": "steer", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "SubmitPayload", - "result_type": "TextResult" - }, - { - "name": "submit", - "surface": "runtime", - "execution": "command", - "permission": "root-admission", - "params_type": "SubmitPayload", - "result_type": "TextResult" - }, - { - "name": "terminal.input", - "surface": "runtime", - "execution": "ephemeral", - "permission": "active-terminal", - "sensitive": true, - "params_type": "TerminalInputParams", - "result_type": "Empty" - }, - { - "name": "tool.call", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ToolCallParams", - "result_type": "TextResult" - }, - { - "name": "tool.configure", - "surface": "runtime", - "execution": "command", - "permission": "tool-permissions", - "params_type": "ToolConfigureParams", - "result_type": "Empty" - }, - { - "name": "tool.schema", - "surface": "runtime", - "execution": "query", - "permission": "tool-authority", - "params_type": "EmptyParams", - "result_type": "ToolSchemaResult" - }, - { - "name": "workspace.inspect", - "surface": "runtime", - "execution": "query", - "permission": "root-association", - "params_type": "EmptyParams", - "result_type": "PathResult" - }, - { - "name": "workspace.set", - "surface": "runtime", - "execution": "command", - "permission": "workspace-authority", - "params_type": "PathParams", - "result_type": "PathResult" - } - ], - "events": { - "browser.command": "BrowserCommand", - "browser.command.cancel": "BrowserCommandCancel", - "browser.inventory": "BrowserInventoryRequest", - "browser.provider.revoked": "BrowserProviderRevoked", - "event": "EventNotification", - "hook.cancel": "ToolCancelParams", - "hook.invoke": "HookInvokeParams", - "sessions.title.changed": "SessionTitleChangedParams", - "subscription.failed": "SubscriptionFailure", - "terminal.detached": "TerminalDetachedParams", - "terminal.exited": "TerminalExitedParams", - "terminal.output": "TerminalOutputParams", - "tool.cancel": "ToolCancelParams", - "tool.invoke": "ToolInvokeParams" - }, - "event_payloads": { - "agent.admitted": "LifecycleEvent", - "agent.prompt.queued": "LifecycleEvent", - "agent.subtree.deleted": "LifecycleEvent", - "agent.subtree.stopped": "LifecycleEvent", - "agent.turn.cancelled": "LifecycleEvent", - "agent.turn.failed": "LifecycleEvent", - "agent.turn.interrupted": "LifecycleEvent", - "agent.turn.started": "LifecycleEvent", - "agent.turn.succeeded": "LifecycleEvent", - "blackboard.append": "LifecycleEvent", - "blackboard.cas": "LifecycleEvent", - "blackboard.set": "LifecycleEvent", - "budget.active_child.reserved": "LifecycleEvent", - "budget.capped": "LifecycleEvent", - "capability.delegated": "LifecycleEvent", - "capability.revoked": "LifecycleEvent", - "command.cancelled": "LifecycleEvent", - "command.control.queued": "LifecycleEvent", - "command.failed": "LifecycleEvent", - "command.interrupted": "LifecycleEvent", - "command.queued": "LifecycleEvent", - "command.running": "LifecycleEvent", - "command.succeeded": "LifecycleEvent", - "command.waiting": "LifecycleEvent", - "goal.continued": "LifecycleEvent", - "inbox.consumed": "LifecycleEvent", - "inbox.failed": "LifecycleEvent", - "inbox.queued": "LifecycleEvent", - "inbox.removed": "LifecycleEvent", - "inbox.running": "LifecycleEvent", - "inbox.steering": "LifecycleEvent", - "message.deferred": "LifecycleEvent", - "message.delivered": "LifecycleEvent", - "message.done": "LifecycleEvent", - "message.queued": "LifecycleEvent", - "message.updated": "LifecycleEvent", - "model.call.corrected": "LifecycleEvent", - "model.call.interrupted": "LifecycleEvent", - "model.call.settled": "LifecycleEvent", - "model.call.started": "LifecycleEvent", - "permission.auto_approved": "LifecycleEvent", - "permission.pending": "LifecycleEvent", - "question.answered": "LifecycleEvent", - "question.closed": "LifecycleEvent", - "question.pending": "LifecycleEvent", - "root.failed": "LifecycleEvent", - "root.interrupted": "LifecycleEvent", - "root.stopped": "LifecycleEvent", - "schedule.fired": "LifecycleEvent", - "scratch.restored": "LifecycleEvent", - "session.archived.updated": "SessionUpdateEvent", - "session.cwd.updated": "SessionUpdateEvent", - "session.effort.updated": "SessionUpdateEvent", - "session.model.updated": "SessionUpdateEvent", - "session.permission_mode.updated": "SessionUpdateEvent", - "session.reload.failed": "LifecycleEvent", - "session.title.updated": "SessionUpdateEvent", - "span.ended": "SpanRecord", - "span.started": "SpanRecord", - "state.private.append": "LifecycleEvent", - "state.private.cas": "LifecycleEvent", - "state.private.set": "LifecycleEvent", - "stream.accounting": "StreamEvent", - "stream.cell.host": "StreamEvent", - "stream.cell.host.started": "StreamEvent", - "stream.discard": "StreamEvent", - "stream.hook.decision": "StreamEvent", - "stream.notice": "StreamEvent", - "stream.reasoning": "StreamEvent", - "stream.terminal.awaiting": "StreamEvent", - "stream.terminal.completed": "StreamEvent", - "stream.terminal.output": "StreamEvent", - "stream.terminal.started": "StreamEvent", - "stream.text": "StreamEvent", - "stream.tool.call": "StreamEvent", - "stream.tool.completed": "StreamEvent", - "stream.tool.output": "StreamEvent", - "stream.tool.progress": "StreamEvent", - "stream.tool.started": "StreamEvent", - "stream.usage": "StreamEvent", - "subscription.cancelled": "LifecycleEvent", - "subscription.created": "LifecycleEvent", - "turn.cancelled": "LifecycleEvent", - "turn.failed": "LifecycleEvent", - "turn.interrupted": "LifecycleEvent", - "turn.started": "LifecycleEvent", - "turn.succeeded": "LifecycleEvent" - } -} diff --git a/packages/protocol/scripts/check.mjs b/packages/protocol/scripts/check.mjs new file mode 100644 index 000000000..971d6b529 --- /dev/null +++ b/packages/protocol/scripts/check.mjs @@ -0,0 +1,15 @@ +import { spawnSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; + +const cwd = fileURLToPath(new URL('../', import.meta.url)); +for (const [command, args] of [ + ['go', ['run', '../../cmd/whip-contract', '-out', 'schema', '-check']], + [process.execPath, ['scripts/generate.mjs', '--check']], +]) { + const { status, error } = spawnSync(command, args, { cwd, stdio: 'inherit' }); + if (status !== 0) { + if (error) console.error(error.message); + console.error('Protocol artifacts could not be verified. Run task generate (run npm ci first on a new checkout).'); + process.exit(status ?? 1); + } +} diff --git a/packages/protocol/scripts/generate.mjs b/packages/protocol/scripts/generate.mjs index c74c13c49..980b92773 100644 --- a/packages/protocol/scripts/generate.mjs +++ b/packages/protocol/scripts/generate.mjs @@ -12,7 +12,7 @@ for (const filename of filenames) { } const manifest = JSON.parse(await readFile('schema/manifest.json', 'utf8')); const operations = surface => manifest.operations.filter(operation => operation.surface === surface); -let declarations = '// Generated from Go wire types. Run npm run generate.\n'; +let declarations = '// Generated from Go wire types. Run task generate.\n'; for (const [name, schema] of Object.entries(schemas)) { declarations += await compile(schema, name, { bannerComment: '', unreachableDefinitions: true }); declarations += '\n'; @@ -90,9 +90,9 @@ function validators(mode) { ajv.addSchema(mode === 'response' ? allowAdditions(schema) : schema); exports[name] = schema.$id; } - return '// Generated standalone validators. Run npm run generate.\n' + standaloneCode(ajv, exports); + return '// Generated standalone validators. Run task generate.\n' + standaloneCode(ajv, exports); } -const runtime = `// Generated from Go wire types. Run npm run generate. +const runtime = `// Generated from Go wire types. Run task generate. import * as requests from './request-validators.js'; import * as responses from './response-validators.js'; export const manifest = ${JSON.stringify(manifest, null, 2)}; @@ -129,7 +129,10 @@ const files = { if (!check) await mkdir('generated', { recursive: true }); for (const [name, expected] of Object.entries(files)) { if (check) { - const actual = await readFile(`generated/${name}`, 'utf8'); - if (actual !== expected) throw new Error(`Generated contract drift: generated/${name}`); + const actual = await readFile(`generated/${name}`, 'utf8').catch(error => { + if (error.code === 'ENOENT') throw new Error(`Missing generated/${name}. Run task generate.`); + throw error; + }); + if (actual !== expected) throw new Error(`Generated contract drift: generated/${name}. Run task generate.`); } else await writeFile(`generated/${name}`, expected); } diff --git a/packages/protocol/scripts/initialization.test.mjs b/packages/protocol/scripts/initialization.test.mjs new file mode 100644 index 000000000..bcfbf92bd --- /dev/null +++ b/packages/protocol/scripts/initialization.test.mjs @@ -0,0 +1,92 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { spawnSync } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const repository = fileURLToPath(new URL('../../../', import.meta.url)); +const generator = fileURLToPath(new URL('./generate.mjs', import.meta.url)); + +test('protocol initialization is repeatable and freshness checks never repair output', async t => { + const directory = await mkdtemp(join(tmpdir(), 'whip-protocol-initialization-')); + t.after(() => rm(directory, { recursive: true, force: true })); + + function run(command, args, cwd) { + const result = spawnSync(command, args, { cwd, encoding: 'utf8' }); + assert.ifError(result.error); + assert.equal(result.signal, null, result.stderr); + return result; + } + const go = check => run('go', ['run', './cmd/whip-contract', '-out', join(directory, 'schema'), + ...(check ? ['-check'] : [])], repository); + const node = check => run(process.execPath, [generator, ...(check ? ['--check'] : [])], directory); + + async function snapshot() { + const files = {}; + for (const name of (await readdir(directory, { recursive: true })).sort()) { + if ((await stat(join(directory, name))).isDirectory()) continue; + files[name] = createHash('sha256').update(await readFile(join(directory, name))).digest('hex'); + } + return files; + } + function generate() { + for (const stage of [go, node]) { + const result = stage(false); + assert.equal(result.status, 0, result.stderr); + } + } + async function check(stage, fresh) { + const before = await snapshot(); + const result = stage(true); + if (fresh) assert.equal(result.status, 0, result.stderr); + else { + assert.notEqual(result.status, 0, 'stale or missing artifacts must fail'); + assert.match(result.stderr, stage === go ? /generated contract/ : /contract drift|ENOENT|Missing generated/i); + } + assert.deepEqual(await snapshot(), before, 'checks must not write artifacts'); + } + + await check(go, false); + await check(node, false); + assert.deepEqual(await readdir(directory), [], 'checks must not initialize missing output directories'); + const schemas = go(false); + assert.equal(schemas.status, 0, schemas.stderr); + await check(node, false); + generate(); + assert.deepEqual((await readdir(join(directory, 'generated'))).sort(), + ['index.d.ts', 'index.js', 'request-validators.js', 'response-validators.js']); + const { validate } = await import(pathToFileURL(join(directory, 'generated/index.js')).href); + const fixtures = JSON.parse(await readFile(join(directory, 'schema/fixtures.json'), 'utf8')); + const subscription = fixtures.find(fixture => fixture.type === 'SubscribeParams'); + assert.equal(validate(subscription.type, subscription.value), true); + assert.equal(validate(subscription.type, { ...subscription.value, cursor: 1 }), false); + + const initialized = await snapshot(); + generate(); + assert.deepEqual(await snapshot(), initialized, 'generation must be byte-for-byte deterministic'); + await check(go, true); + await check(node, true); + + const schemaPath = join(directory, 'schema/SubscribeParams.json'); + const schema = JSON.parse(await readFile(schemaPath, 'utf8')); + await writeFile(schemaPath, JSON.stringify({ ...schema, description: 'Stale contract' })); + await check(go, false); + await check(node, false); + generate(); + + const runtimePath = join(directory, 'generated/index.js'); + await writeFile(runtimePath, (await readFile(runtimePath, 'utf8')) + '\n// stale output\n'); + await check(node, false); + await rm(runtimePath); + await check(node, false); + await rm(schemaPath); + await check(go, false); + generate(); + await writeFile(join(directory, 'schema/RemovedContract.json'), '{}\n'); + await check(go, false); + generate(); + assert.deepEqual(await snapshot(), initialized, 'refresh must restore missing output and remove obsolete schemas'); +}); diff --git a/packages/sdk/README.md b/packages/sdk/README.md index acbfa2804..4cc00cd4b 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -15,9 +15,11 @@ the daemon and clients together; older majors fail during initialization. ## Install and check in this repository +Use Node 24, the Go toolchain in `go.mod`, and Task from the repository root: + ```sh npm ci -npm run build +task generate npm run check npm run acceptance npm run test:package @@ -29,6 +31,14 @@ optional synchronized views, and `/react` adds optional React subscriptions. Core and state do not import React or Node built-ins. React consumers supply React 19. Both packages remain private; package-archive installation is tested. +`task generate` creates the ignored protocol schemas and generated code from Go, +then builds the SDK. Rerun it after pulling, switching branches, or editing +protocol definitions/generators; rerun `npm ci` first when dependencies change. +For SDK-only source edits, `npm run build` recompiles the SDK. Ordinary builds do +not generate the protocol; freshness checks reject stale or missing artifacts. +Prepared package archives include the JavaScript and declarations consumers need +and work without Go or install scripts. + ## Attach and submit ```ts @@ -741,10 +751,9 @@ Host/Origin checks remain exact, not authentication; remote access requires a trusted network or authenticated proxy. The whipcode distribution uses `WHIPCODE_*`. See [web setup](../../docs/web-app.md). -Start the example with: +After initializing the workspace above, start the example with: ```sh -npm run build npm start -w @whip/client-example ``` diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 17894e29e..f9d9bde4d 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -17,7 +17,8 @@ "scripts": { "build": "tsc -p tsconfig.json", "check": "npm run build && npm test", - "test": "tsc -p tsconfig.test.json && node --test build/test/*.test.js" + "test": "tsc -p tsconfig.test.json && node --test build/test/*.test.js", + "prepack": "npm run check:drift -w @whip/protocol" }, "dependencies": { "@whip/protocol": "3.0.0" }, "peerDependencies": { "react": "^19.0.0" }, diff --git a/packages/sdk/scripts/package-smoke.mjs b/packages/sdk/scripts/package-smoke.mjs index 156cc1d14..b34c64df1 100644 --- a/packages/sdk/scripts/package-smoke.mjs +++ b/packages/sdk/scripts/package-smoke.mjs @@ -13,7 +13,13 @@ try { const { stdout } = await execute('npm', ['pack', '--json', '--pack-destination', directory], { cwd: join(repository, 'packages', name) }); const [packed] = JSON.parse(stdout); archives[`@whip/${name}`] = 'file:' + join(directory, packed.filename); - if (packed.files.some(file => /(^|\/)(node_modules|src|test|build)\//.test(file.path))) throw new Error(`Unexpected development files in @whip/${name}`); + if (packed.files.some(file => /(^|\/)(node_modules|src|test|build|schema|scripts)\//.test(file.path))) throw new Error(`Unexpected development files in @whip/${name}`); + if (name === 'protocol') { + for (const file of ['index.js', 'index.d.ts', 'request-validators.js', 'response-validators.js']) { + if (!packed.files.some(entry => entry.path === `generated/${file}` && entry.size > 0)) + throw new Error(`Protocol archive is missing generated/${file}`); + } + } } const consumer = join(directory, 'consumer'); await mkdir(consumer); diff --git a/scripts/docker/onboarding.Dockerfile b/scripts/docker/onboarding.Dockerfile index cd245bf1b..afd519b7d 100644 --- a/scripts/docker/onboarding.Dockerfile +++ b/scripts/docker/onboarding.Dockerfile @@ -2,18 +2,26 @@ ARG NODE_VERSION=24 ARG GO_VERSION=1.27.0 +FROM golang:${GO_VERSION}-bookworm AS go-toolchain + FROM node:${NODE_VERSION}-bookworm-slim AS web +COPY --from=go-toolchain /usr/local/go /usr/local/go +COPY --from=go-toolchain /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +ENV PATH=/usr/local/go/bin:$PATH GOPATH=/go WORKDIR /src # Preserve workspace paths while caching installation independently of source edits. COPY --parents package.json package-lock.json packages/*/package.json apps/*/package.json examples/*/package.json ./ RUN --mount=type=cache,target=/root/.npm \ ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm ci --no-audit --no-fund COPY . . +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + npm run generate && npm run build ARG WHIP_RENDERER_LOCAL_SOURCE -RUN WHIP_RENDERER_LOCAL_SOURCE="$WHIP_RENDERER_LOCAL_SOURCE" npm run build:web \ +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \ + WHIP_RENDERER_LOCAL_SOURCE="$WHIP_RENDERER_LOCAL_SOURCE" npm run build:web \ && node scripts/pack-web.mjs -FROM golang:${GO_VERSION}-bookworm AS build +FROM go-toolchain AS build WORKDIR /src COPY go.mod go.sum ./ RUN --mount=type=cache,target=/go/pkg/mod go mod download diff --git a/scripts/docker/onboarding.Dockerfile.dockerignore b/scripts/docker/onboarding.Dockerfile.dockerignore index 1a5db1011..819258ec9 100644 --- a/scripts/docker/onboarding.Dockerfile.dockerignore +++ b/scripts/docker/onboarding.Dockerfile.dockerignore @@ -22,6 +22,8 @@ internal/tui/whip-transcript-*.md internal/webassets/dist packages/sdk/dist packages/sdk/build +packages/protocol/schema +packages/protocol/generated packages/ui/storybook-static examples/*/dist apps/*/dist diff --git a/scripts/pack-web.mjs b/scripts/pack-web.mjs index 3b5a03fb2..388952271 100644 --- a/scripts/pack-web.mjs +++ b/scripts/pack-web.mjs @@ -1,10 +1,12 @@ // Copy only the built browser output into go:embed's input. Never reads host data. import { cp, mkdir, readFile, readdir, rm, lstat, writeFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; +import { execFileSync } from 'node:child_process'; import path from 'node:path'; import { readRendererManifest, verifyRenderer, verifyRendererProvenance } from './renderer-artifact.mjs'; const root = fileURLToPath(new URL('../', import.meta.url)); +execFileSync(process.execPath, [path.join(root, 'packages/protocol/scripts/check.mjs')], { stdio: 'inherit' }); const source = path.join(root, 'apps/web/dist'); const target = path.join(root, 'internal/webassets/dist'); const manifest = await readRendererManifest(path.join(root, 'apps/web/renderer-manifest.json')); diff --git a/scripts/pack-web.test.mjs b/scripts/pack-web.test.mjs index bd2549796..3b907688f 100644 --- a/scripts/pack-web.test.mjs +++ b/scripts/pack-web.test.mjs @@ -14,6 +14,8 @@ async function fixture(t) { const source = path.join(root, 'apps/web/dist'); const target = path.join(root, 'internal/webassets/dist'); await mkdir(path.join(root, 'scripts'), { recursive: true }); + await mkdir(path.join(root, 'packages/protocol/scripts'), { recursive: true }); + await writeFile(path.join(root, 'packages/protocol/scripts/check.mjs'), ''); await mkdir(path.join(source, 'assets'), { recursive: true }); await mkdir(target, { recursive: true }); await copyFile(new URL('./pack-web.mjs', import.meta.url), path.join(root, 'scripts/pack-web.mjs')); @@ -39,6 +41,14 @@ test('packages the real build tree and removes stale generated assets', async t await assert.rejects(readFile(path.join(f.target, 'stale.js')), { code: 'ENOENT' }); }); +test('refuses stale protocol artifacts before replacing the previous bundle', async t => { + const f = await fixture(t); + await writeFile(path.join(f.root, 'packages/protocol/scripts/check.mjs'), + 'console.error("Protocol artifacts could not be verified. Run task generate."); process.exit(1);'); + await assert.rejects(f.run(), /Run task generate/); + assert.equal(await readFile(path.join(f.target, 'stale.js'), 'utf8'), 'old build'); +}); + test('rejects missing app entry before replacing the previous bundle', async t => { const f = await fixture(t); await writeFile(path.join(f.source, 'index.html'), '<html>broken</html>'); diff --git a/scripts/test-publish-whipcode.py b/scripts/test-publish-whipcode.py index 916c0f8ae..6db7f7db9 100644 --- a/scripts/test-publish-whipcode.py +++ b/scripts/test-publish-whipcode.py @@ -514,16 +514,23 @@ def test_candidate_attestation_matches_admitted_source_workflow(self): self.assertIn('release-candidate.mjs verify candidate', publish) self.assertIn('--deny-self-hosted-runners', publish) - def test_candidate_run_steps_install_dependencies_before_node(self): + def test_candidate_run_steps_initialize_workspace_before_node(self): candidate = self.job(self.release, 'candidate') # Exercise run-step ordering in an empty workspace; the fake node fails - # unless npm ci actually ran with Electron downloads disabled first. + # unless dependencies, protocol generation, and SDK compilation ran first. with tempfile.TemporaryDirectory(prefix='candidate-workspace-') as directory: root = Path(directory) (root / 'candidate').mkdir() (root / 'install.sh').write_text('installer') - (root / 'npm').write_text('#!/bin/sh\n[ "$1" = ci ] && [ "$ELECTRON_SKIP_BINARY_DOWNLOAD" = 1 ] || exit 1\ntouch dependencies-ready\n') - (root / 'node').write_text('#!/bin/sh\ntest -f dependencies-ready || exit 1\ncase "$1" in scripts/build-installers.mjs) printf pinned > candidate/install.sh; printf stable > candidate/latest.sh;; *) test -s candidate/install.sh && test -s candidate/latest.sh || exit 1; touch assembled;; esac\n') + (root / 'npm').write_text('''#!/bin/sh +case "$*" in + ci) [ "$ELECTRON_SKIP_BINARY_DOWNLOAD" = 1 ] || exit 1; touch dependencies-ready;; + 'run generate') test -f dependencies-ready || exit 1; touch protocol-ready;; + 'run build') test -f protocol-ready || exit 1; touch sdk-ready;; + *) exit 1;; +esac +''') + (root / 'node').write_text('#!/bin/sh\ntest -f sdk-ready || exit 1\ncase "$1" in scripts/build-installers.mjs) printf pinned > candidate/install.sh; printf stable > candidate/latest.sh;; *) test -s candidate/install.sh && test -s candidate/latest.sh || exit 1; touch assembled;; esac\n') for executable in ['npm', 'node']: (root / executable).chmod(0o755) env = {**os.environ, 'PATH': str(root) + os.pathsep + os.environ['PATH'], 'RELEASE_TAG': 'v1.0.1-alpha.1'} @@ -543,7 +550,7 @@ def test_candidate_run_steps_install_dependencies_before_node(self): capture_output=True, text=True, timeout=10) self.assertEqual(result.returncode, 0, result.stderr) executed += 1 - self.assertEqual(executed, 2) + self.assertEqual(executed, 3) self.assertTrue((root / 'assembled').exists()) def test_distribution_installer_dependencies_precede_execution(self): diff --git a/scripts/update-local.mjs b/scripts/update-local.mjs index ad831e4a9..11704393e 100644 --- a/scripts/update-local.mjs +++ b/scripts/update-local.mjs @@ -26,7 +26,8 @@ See README.md for details and recovery. No Git pull or release publication occur async function build(env) { // Git dependencies resolve their own build tooling; revalidate cached registry metadata. - for (const [file, args] of [['npm', ['ci', '--prefer-online']], [process.execPath, ['node_modules/electron/install.js']], + for (const [file, args] of [['npm', ['ci', '--prefer-online']], + ['npm', ['run', 'generate']], ['npm', ['run', 'build']], [process.execPath, ['node_modules/electron/install.js']], [process.execPath, ['apps/desktop/scripts/package.mjs']]]) { await new Promise((resolve, reject) => { const child = spawn(file, args, { cwd: repositoryRoot, stdio: 'inherit', env }); From be31efefe3edb134306ff5c4eda5a3c94e90fbc4 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Mon, 28 Sep 2026 16:56:47 -0700 Subject: [PATCH 12/67] feat(llm): native anthropic-messages API flavor Claude models on inference.net advertise supported_endpoints: ["messages"] only, but whip posted OpenAI chat-completions to them; the gateway's OpenAI-to-Anthropic translation is lossy for thinking models, and the second tool round of a thinking-enabled session 400s as an opaque upstream error (Anthropic requires signature-carrying thinking blocks replayed with tool_use; chat history cannot represent them). Add a third API flavor, anthropic-messages, opt-in per provider entry: - internal/llm/messages.go: encodeMessages translates history natively (system hoisting, tool_use/tool_result blocks, native tool schemas, Anthropic SSE parsing with thinking+signature capture), and messagesOnce posts to {baseURL}/messages with Bearer + x-api-key and anthropic-version headers. - Message.Thinking []ThinkingBlock persists captured thinking with signatures in the session store (legacy sessions decode with it nil); encodeMessages replays thinking before tool_use, and the chat encoder strips it via a copy so captured blocks never reach a chat endpoint. - reasoning_effort maps to thinking.budget_tokens (1024-32768 by level, floored at the 1024 minimum, capped at max_tokens/2 so thinking cannot squeeze out all visible output); off/none omit thinking; unknown levels error loudly instead of guessing. - config.APIMessages + KnownAPI/GenericChatAPI replace the scattered API != openai-completions validation so the flavor is admitted across daemon gates; daemon.ModelClient builds a messages client when the provider entry opts in. Live-validated against api.inference.net/v1/messages with claude-opus-5-5: 200 OK, correct Anthropic response and usage shape. Sessions revert to chat-completions by removing the api field; no session schema changes beyond the additive Thinking field. --- .ai-docs/plans/anthropic-messages/PLAN.md | 134 ++++++++ docs/models-providers.md | 13 +- internal/config/config.go | 30 +- internal/config/providers.go | 4 +- internal/daemon/provider_configuration.go | 2 +- internal/daemon/provider_list.go | 6 +- internal/daemon/provider_model.go | 3 + internal/daemon/provider_service.go | 2 +- internal/llm/accounting.go | 5 +- internal/llm/messages.go | 367 +++++++++++++++++++++ internal/llm/messages_test.go | 374 ++++++++++++++++++++++ internal/llm/openai.go | 64 +++- internal/llm/provider_compatibility.go | 22 ++ 13 files changed, 1011 insertions(+), 15 deletions(-) create mode 100644 .ai-docs/plans/anthropic-messages/PLAN.md create mode 100644 internal/llm/messages.go create mode 100644 internal/llm/messages_test.go diff --git a/.ai-docs/plans/anthropic-messages/PLAN.md b/.ai-docs/plans/anthropic-messages/PLAN.md new file mode 100644 index 000000000..7e8ea3e47 --- /dev/null +++ b/.ai-docs/plans/anthropic-messages/PLAN.md @@ -0,0 +1,134 @@ +# Plan: native `anthropic-messages` API flavor (inference.net) + +Status: phase 1 implemented (slice 1, thinking off); phase 0 live-run pending +Implementation: internal/llm/messages.go, llm.Flavor dispatch in openai.go/accounting.go, +config.APIMessages + KnownAPI/GenericChatAPI in config.go, daemon ModelClient wiring, +API gate checks now via config.KnownAPI. Tests: internal/llm/messages_test.go. +Date: 2026-09-28 +Related: `.ai-docs/plans/agent-ux-batch/opencode-speed.md` (mentions anthropic-messages); +`docs/models-providers.md:133` (documents the current two-flavor limitation) + +## Problem + +Claude models on inference.net (`claude-opus-5-5` etc.) advertise +`supported_endpoints: ["messages"]` only — they speak Anthropic Messages, not +chat-completions. whip (`api: "openai-completions"`) posts chat-completions +anyway, and inference.net's OpenAI→Anthropic translation layer breaks on +tool-round replays. Result: opaque `400 invalid_request_error "the upstream +provider returned an error"` on the second tool round of a thinking-enabled +Claude session. + +Root cause chain (diagnosed on main @ 801b3a4f): +effort "low" default → translator enables Anthropic thinking → Anthropic +requires thinking blocks replayed with tool_use turns (with signature) → +whip's history stores only text/tool calls → second-round request is +protocol-invalid. + +Interim hotfix already in the tree (uncommitted): +`internal/llm/provider_compatibility.go` strips `reasoning_effort` from +Claude-via-OpenRouter routes (same treatment DeepSeek V4 gets). This makes the +400 stop happening, at the cost of Claude thinking being unreachable. + +## Phase 0 — evidence before code (no build) + +Run the extracted repro matrix against `https://api.inference.net/v1/chat/completions` +(bodies producible via `go run ./cmd/dumprequest <model> <effort>`, added in this +branch, plus the hand-built round-2 replay in this plan's discussion): + +| Variant | Confirms/refutes | +|---|---| +| round 1, effort present vs absent | whether inf.net maps effort→thinking | +| round 2 (assistant tool_calls + tool result, content ""), effort present | the 400 repro | +| same round 2, effort removed | thinking-replay invariant is the trigger | +| same round 2, `"content": null` | empty-text-block translation bug | + +Findings decide whether slice 1 needs any extra guard. If the opaque wrapper +swallows Anthropic's field-level detail, note it: it justifies the adapter's +error-surfacing behavior (real `type`/`message` from /v1/messages). + +## Phase 1 — slice 1: native Messages flavor, thinking OFF (~250 lines) + +Smallest thing that fixes the protocol mismatch without new invariants. + +1. **Config opt-in, not catalog magic.** Add `"anthropic-messages"` as a + valid `api` value (`internal/config/config.go:21` comment, validation at + `config.go:196`). User sets `"api": "anthropic-messages"` on the + inference-net provider (config is guarded/atomic; no catalog-keyed silent + protocol switches in v1 of this feature — a stale `~/.whip/models.json` + must never change wire protocol). +2. **`internal/llm/messages.go`** — mirror `responses.go`: + - `encodeMessages(req Request)`: system role → top-level `system`; + user Parts → text/image blocks; tool → `{role:"user", + content:[{type:"tool_result",...}]}`; tools → `{name, description, + input_schema}`; **no reasoning_effort** (thinking stays off in slice 1 — + the budget mapping is unguessable and wrong values are hard 400s); + no prompt_cache_key equivalent. + - `messagesOnce(...)`: Anthropic SSE (`message_start`, content_block_*, + `message_delta` usage, `message_stop`) → onText/onToolCall; posts to + `{BaseURL}/messages` (parameterize `httpRequest`). + onThink unused in slice 1. +3. **Dispatch**: `Client.Stream`/`Complete` select Messages when the + provider `api` says so (a `Client.flavor` field set at client + construction from config; NOT derived from BaseURL string-matching for + inference.net — the existing encodeChatRequest switch stays + for-compat only). Reuses `runAttempt` retry/regeneration untouched. +4. **Docs**: `docs/models-providers.md` flavor list; `docs/features.md` entry. +5. **Tests**: encode golden tests (every role, tool round-trip — the exact + 400 case minus thinking must encode cleanly); SSE parse tests; an + end-to-end fake-server tool round-trip; the provider_compatibility + suite extended so no Claude-with-effort request reaches chat-completions. +6. **Live verification**: extend `cmd/dumprequest` with flavor awareness, + then run the phase-0 matrix against real `/v1/messages`. Turn 1 + tool + round 2 must go green with native error text visible on failure. + +Shippable on its own: Claude-on-inf.net gets native protocol, real errors, +and the same thinking-off behavior as the hotfix, but now as a deliberate +correct protocol rather than a suppressed parameter. + +## Phase 2 — thinking: capture + replay WITH signatures (decoupled follow-up) + +Only after slice 1 is live and we can harvest real signatures. + +1. Replay must echo the encrypted signature Anthropic returns — not the raw + `reasoning_content` text whip sees on the chat path. So: capture + `{type:"thinking", thinking, signature}` blocks from /v1/messages + `content_block_start/delta` events into a new internal `Message` field + (persisted; old sessions unmarshal with it empty — backward compatible). +2. `encodeMessages` emits thinking blocks before tool_use on replay. +3. Effort → `thinking.budget_tokens`: derive mapping from live errors and + docs per model family; keep the hotfix guard for any chat-completions + Claude route that remains (OpenRouter etc.). +4. Swap inference-net's own preset in `internal/config/providers.go` to + `anthropic-messages` for Claude ids only after phase 2 verification, OR + leave user-opt-in and revisit. +5. Optional: reject `attendance` mismatch early — validate a session's + replayed history against Anthropic's requirements client-side (thinking + present iff tool_use present on replay) so bugs surface as clear local + errors, not upstream 400s. + +## Explicit non-goals (for now) + +- Catalog-driven flavor selection (`supported_endpoints` → protocol). Deferred + until phase 2 is proven; risk of silent mid-session protocol flip. +- `cache_control` prompt caching breakpoints for Anthropic. Follow-up; + `prompt_cache_key` has no Anthropic meaning. +- Bedrock/Vertex variants, OpenRouter Claude conversion to native (the + hotfix guard continues to cover it). + +## Risks / notes + +- Thinking MUST stay off in slice 1 (both by omission and by guarding against + config leftovers). A `reasoning_effort` on a messages-flavor request is a + silent no-op at best; the guard belongs in `encodeMessages` as a lint-level + check so it can be removed in phase 2, not forgotten. +- Session store schema is untouched in slice 1 (phase 2 adds one field). +- No new dependencies. All dispatch passes through existing retry machinery. + +## Verification checklist + +- [ ] Phase 0 matrix run and results recorded here +- [ ] slice 1: fake-server tool round-trip test green +- [ ] slice 1: live inf.net turn 1 + tool round 2 green via /v1/messages +- [ ] slice 1: `task check` green, docs updated +- [ ] phase 2: signature-carrying replay verified against live error text +- [ ] phase 2: effort→budget mapping derived from real responses, not guessed diff --git a/docs/models-providers.md b/docs/models-providers.md index 705e1caf0..dd321fe0f 100644 --- a/docs/models-providers.md +++ b/docs/models-providers.md @@ -130,10 +130,15 @@ source below, or paste the key in Whip. Existing Whip keys and account files are preserved. Docker continues to isolate your host credentials unless you explicitly seed a test source inside the container. -The runtime supports two API flavors: `openai-completions` for OpenAI-compatible -Chat Completions, and `openai-codex` for the fixed ChatGPT subscription endpoint. -There is no native Anthropic Messages, Google Gemini, or configurable generic -Responses API adapter. Models served through a compatible gateway still work. +The runtime supports three API flavors: `openai-completions` for OpenAI-compatible +Chat Completions, `openai-codex` for the fixed ChatGPT subscription endpoint, and +`anthropic-messages`, which speaks Anthropic Messages natively. Set it on a +provider entry (`"api": "anthropic-messages"`) whose models expose a messages +endpoint — inference.net's Claude models advertise `supported_endpoints: +["messages"]`, and the chat-completions translation for them is lossy for +thinking- and tool-round-trip requests. Thinking parameters are not yet sent on +the messages flavor (phase 2). Models served through a chat-compatible gateway +still work unchanged. In the TUI, open `/connect` and choose **Custom endpoint**. Compact prompts ask for a name, the API root URL (for example `https://api.example.com/v1`), and choose API key, diff --git a/internal/config/config.go b/internal/config/config.go index 29a16f17b..8f538a932 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,13 +12,41 @@ import ( "strings" "github.com/context-labs/whip/internal/buildinfo" + "github.com/context-labs/whip/internal/openaiauth" ) +// API flavor constants. The zero value and APICompletions mean the generic +// OpenAI-compatible chat-completions wire protocol; APICodex is the fixed +// ChatGPT subscription endpoint (openaiauth.Provider); APIMessages speaks +// Anthropic Messages natively (internal/llm/messages.go). +const ( + APICompletions = "openai-completions" + APICodex = openaiauth.Provider + APIMessages = "anthropic-messages" +) + +// KnownAPI reports whether s names a supported provider API flavor. The empty +// string is valid: it means APICompletions (the historical default). +func KnownAPI(s string) bool { + switch s { + case "", APICompletions, APICodex, APIMessages: + return true + } + return false +} + +// GenericChatAPI reports whether s is the generic chat-completions wire +// contract (open to custom endpoints and setup forms). Codex and Messages are +// fixed-protocol providers, not generic endpoints. +func GenericChatAPI(s string) bool { + return s == "" || s == APICompletions +} + // Provider is an API endpoint that can serve models. type Provider struct { Name string `json:"name,omitempty"` BaseURL string `json:"baseUrl"` - API string `json:"api"` // "openai-completions" or "openai-codex" + API string `json:"api"` // flavor constant, see api.go APIKey string `json:"apiKey,omitempty"` // literal key or a secret reference ("$VAR"/"${VAR}"/"!cmd"); apiKeyEnv is another option APIKeyEnv string `json:"apiKeyEnv,omitempty"` Auth string `json:"auth,omitempty"` // "none" explicitly disables authentication; omitted resolves a key diff --git a/internal/config/providers.go b/internal/config/providers.go index fbf04630c..a376b4a8b 100644 --- a/internal/config/providers.go +++ b/internal/config/providers.go @@ -193,7 +193,7 @@ func openAIEnvironmentMatches() bool { } func canonicalPreset(p Provider) (ProviderPreset, bool) { - if p.API != "" && p.API != "openai-completions" { + if p.API != "" && !KnownAPI(p.API) { return ProviderPreset{}, false } for _, preset := range ProviderPresets() { @@ -268,7 +268,7 @@ func (p Provider) ValidateAuth() error { if p.Auth != "" && p.Auth != "none" { return errors.New("unsupported provider authentication mode") } - if p.Auth == "none" && (p.APIKey != "" || p.APIKeyEnv != "" || p.API != "" && p.API != "openai-completions") { + if p.Auth == "none" && (p.APIKey != "" || p.APIKeyEnv != "" || p.API != "" && !GenericChatAPI(p.API)) { return errors.New("unauthenticated providers cannot contain credentials or use subscription APIs") } return nil diff --git a/internal/daemon/provider_configuration.go b/internal/daemon/provider_configuration.go index 574bc6345..d5f1d4b7f 100644 --- a/internal/daemon/provider_configuration.go +++ b/internal/daemon/provider_configuration.go @@ -130,7 +130,7 @@ func validateProviderDefinition(provider config.Provider) error { if strings.TrimSpace(provider.Name) == "" || len(provider.Name) > 256 || strings.IndexFunc(provider.Name, unicode.IsControl) >= 0 { return errors.New("provider name is required and must be at most 256 characters") } - if provider.API != "" && provider.API != "openai-completions" { + if provider.API != "" && !config.KnownAPI(provider.API) { return errors.New("custom providers require the OpenAI-compatible Chat Completions API") } endpoint, err := url.Parse(provider.BaseURL) diff --git a/internal/daemon/provider_list.go b/internal/daemon/provider_list.go index 36da3019b..bf6302864 100644 --- a/internal/daemon/provider_list.go +++ b/internal/daemon/provider_list.go @@ -50,7 +50,7 @@ func (s *ProviderService) ListProvidersFor(model, provider string) (protocol.Pro if preset.ID == config.InferenceNetProvider && inferenceNetLoginRoute(cfg) != nil { entry.Methods = []string{"api_key"} } - if preset.ID != openaiauth.Provider && route.API != "" && route.API != "openai-completions" { + if preset.ID != openaiauth.Provider && route.API != "" && !config.KnownAPI(route.API) { entry.Methods = []string{} } } @@ -178,7 +178,7 @@ func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentia } endpoint, endpointErr := url.Parse(entry.BaseURL) validEndpoint := endpointErr == nil && endpoint.Host != "" && (endpoint.Scheme == "https" || endpoint.Scheme == "http") && endpoint.User == nil && endpoint.RawQuery == "" && endpoint.Fragment == "" - if !validEndpoint || (entry.API != "" && entry.API != "openai-completions") || entry.ValidateAuth() != nil { + if !validEndpoint || (entry.API != "" && !config.KnownAPI(entry.API)) || entry.ValidateAuth() != nil { result.AuthState, result.Available = "configuration_error", new(false) result.Warnings = append(result.Warnings, "This provider requires a supported API configuration.") } @@ -195,7 +195,7 @@ func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentia func inferenceNetLoginRoute(cfg *config.Config) error { if route, exists := cfg.Providers[config.InferenceNetProvider]; exists { - if strings.TrimRight(route.BaseURL, "/") != config.InferenceNetBaseURL || (route.API != "" && route.API != "openai-completions") { + if strings.TrimRight(route.BaseURL, "/") != config.InferenceNetBaseURL || (route.API != "" && !config.KnownAPI(route.API)) { return errors.New("account login to Inference.net requires its built-in endpoint; the saved custom provider was left unchanged") } } diff --git a/internal/daemon/provider_model.go b/internal/daemon/provider_model.go index 161a5b710..e571ec3a4 100644 --- a/internal/daemon/provider_model.go +++ b/internal/daemon/provider_model.go @@ -46,6 +46,9 @@ func (s *ProviderService) ModelClient(provider config.Provider, configs ...*conf if key == "" && provider.Auth != "none" { return nil, errors.New("no API key for provider") } + if provider.API == config.APIMessages { + return llm.NewMessagesClient(provider.BaseURL, key), nil + } return llm.New(provider.BaseURL, key), nil } diff --git a/internal/daemon/provider_service.go b/internal/daemon/provider_service.go index 434fb44bd..25aa162e8 100644 --- a/internal/daemon/provider_service.go +++ b/internal/daemon/provider_service.go @@ -364,7 +364,7 @@ func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup provider.APIKeyEnv = config.DiscoverCredentials(c).AvailableEnvironmentVariable(preset) } } - if !ok || (provider.API != "" && provider.API != "openai-completions") { + if !ok || (provider.API != "" && !config.KnownAPI(provider.API)) { return RuntimeConfiguration{}, errors.New("provider does not support API key setup") } credential := protocol.ProviderCredential{Mode: "api_key", Key: p.Key} diff --git a/internal/llm/accounting.go b/internal/llm/accounting.go index 8b162293a..4b0b43427 100644 --- a/internal/llm/accounting.go +++ b/internal/llm/accounting.go @@ -453,6 +453,9 @@ func (c *Client) runAttempt(ctx context.Context, req Request, logicalID string, body, err = encodeResponses(req, credentials.AccountID) } else if c.apiResponses(req.Model) { body, err = encodeResponsesWithLimit(req, c.apiResponseScope(), req.MaxTokens) + } else if c.Flavor == FlavorMessages { + req.Messages = stripAuthored(req.Messages) + body, err = encodeMessages(req) } else { req.Messages = stripAuthored(req.Messages) body, err = c.encodeChatRequest(req) @@ -460,7 +463,7 @@ func (c *Client) runAttempt(ctx context.Context, req Request, logicalID string, if err != nil { return Message{}, Usage{}, settle(ModelAttemptResult{Failed: true}, nonRetryable{err}) } - if _, err := httpRequest(ctx, c.BaseURL, body); err != nil { + if _, err := c.newRequest(ctx, body); err != nil { return Message{}, Usage{}, settle(ModelAttemptResult{Failed: true}, nonRetryable{err}) } if err := ctx.Err(); err != nil { diff --git a/internal/llm/messages.go b/internal/llm/messages.go new file mode 100644 index 000000000..248d44ced --- /dev/null +++ b/internal/llm/messages.go @@ -0,0 +1,367 @@ +package llm + +// Messages flavor: speak Anthropic Messages natively rather than through a +// chat-completions translation layer. The translation is lossy for thinking +// models (the translator enables thinking but whip's history cannot replay +// signature-carrying thinking blocks with tool_use, so the second tool round +// 400s opaque upstream errors) and for models that only expose a messages +// endpoint at all. Slice 1 deliberately does not send thinking; see PLAN.md +// (phase 2) for signature capture. + +import ( + "bufio" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strings" +) + +// imageMediaType extracts the media type from a data: URL image part; +// falls back to png for malformed values. +func imageMediaType(dataURL string) string { + if !strings.HasPrefix(dataURL, "data:") { + return "image/png" + } + rest := strings.TrimPrefix(dataURL, "data:") + if i := strings.Index(rest, ";"); i > 0 { + return rest[:i] + } + return "image/png" +} + +// imageData strips a data: URL to its base64 payload. +func imageData(dataURL string) string { + if i := strings.Index(dataURL, ","); i > 0 { + return dataURL[i+1:] + } + return "" +} + +const anthropicMessagesPath = "/messages" + +// encodeMessages translates a Request into the Anthropic Messages body. +// thinkingBudgetTokens maps whip's reasoning-effort ladder to Anthropic +// thinking budget_tokens, floored at Anthropic's documented minimum (1024). +// Values are conservative: budgets cap thinking tokens per request and are +// subtracted from the max_tokens ceiling, so generous defaults risk truncating +// visible output on small max_tokens calls. +var thinkingBudgetTokens = map[string]int{ + "minimal": 1024, + "low": 2048, + "medium": 4096, + "high": 8192, + "xhigh": 16384, + "max": 32768, +} + +func encodeMessages(req Request) ([]byte, error) { + maxTokens := req.MaxTokens + if maxTokens <= 0 { + maxTokens = 8192 + } + thinkingEnabled := req.ReasoningEffort != "" && req.ReasoningEffort != "off" && req.ReasoningEffort != "none" + budget := 0 + if thinkingEnabled { + if cap, ok := thinkingBudgetTokens[req.ReasoningEffort]; ok { + // Anthropic requires max_tokens > budget_tokens; leave room for + // visible output by capping the budget at half the ceiling. + budget = min(cap, maxTokens/2) + } else { + // Unknown effort level: a wrong budget is a hard 400 upstream. + // Fail loudly rather than guess. + return nil, fmt.Errorf("anthropic-messages: unsupported reasoning effort %q", req.ReasoningEffort) + } + budget = max(budget, 1024) // documented minimum + } + // When thinking is on but history carries no thinking blocks (sessions + // predating capture, or the turn itself), Anthropic still accepts the + // request — thinking need only be replayed once emitted.. + var system []string + blocks := []any{} + for _, message := range req.Messages { + switch message.Role { + case "system", "developer": + system = append(system, message.TextContent()) + case "user": + content, err := anthropicUserContent(message) + if err != nil { + return nil, err + } + blocks = append(blocks, map[string]any{"role": "user", "content": content}) + case "assistant": + content := []any{} + for _, block := range message.Thinking { + // Replay captured thinking ahead of tool_use, signature + // verbatim — Anthropic validates the pairing and the + // signature on every thinking-enabled tool round. + content = append(content, map[string]any{ + "type": "thinking", "thinking": block.Thinking, "signature": block.Signature, + }) + } + if message.Content != "" { + content = append(content, map[string]any{"type": "text", "text": message.Content}) + } + for _, call := range message.ToolCalls { + var input any + if err := json.Unmarshal([]byte(call.Function.Arguments), &input); err != nil { + return nil, fmt.Errorf("anthropic-messages: tool call %q arguments: %w", call.Function.Name, err) + } + content = append(content, map[string]any{ + "type": "tool_use", "id": call.ID, "name": call.Function.Name, "input": input, + }) + } + blocks = append(blocks, map[string]any{"role": "assistant", "content": content}) + case "tool": + blocks = append(blocks, map[string]any{ + "role": "user", + "content": []any{map[string]any{ + "type": "tool_result", "tool_use_id": message.ToolCallID, "content": message.TextContent(), + }}, + }) + default: + return nil, fmt.Errorf("anthropic-messages: unsupported message role %q", message.Role) + } + } + var tools []any + for _, tool := range req.Tools { + var schema any + if err := json.Unmarshal(tool.Function.Parameters, &schema); err != nil { + return nil, fmt.Errorf("anthropic-messages: tool %q schema: %w", tool.Function.Name, err) + } + tools = append(tools, map[string]any{ + "name": tool.Function.Name, "description": tool.Function.Description, "input_schema": schema, + }) + } + body := map[string]any{ + "model": req.Model, "messages": blocks, "stream": true, + "anthropic_version": "2023-06-01", + } + if len(system) > 0 { + body["system"] = strings.Join(system, "\n\n") + } + if len(tools) > 0 { + body["tools"] = tools + } + if req.MaxTokens > 0 { + body["max_tokens"] = req.MaxTokens + } + if req.Temperature != nil { + body["temperature"] = *req.Temperature + } + if req.TopP != nil { + body["top_p"] = *req.TopP + } + if thinkingEnabled { + body["thinking"] = map[string]any{"type": "enabled", "budget_tokens": budget} + } + // prompt_cache_key and stream_options have no Messages meaning; omitted. + return json.Marshal(body) +} + +func anthropicUserContent(message Message) ([]any, error) { + content := []any{} + if message.Content != "" { + content = append(content, map[string]any{"type": "text", "text": message.Content}) + } + for _, part := range message.Parts { + switch part.Type { + case "text": + content = append(content, map[string]any{"type": "text", "text": part.Text}) + case "image_url": + if part.ImageURL == nil { + return nil, errors.New("anthropic-messages: image part has no URL") + } + content = append(content, map[string]any{ + "type": "image", + "source": map[string]any{ + "type": "base64", + // split a data: URL into media type and payload; seen as + // source.base64 format in Messages + "media_type": imageMediaType(part.ImageURL.URL), + "data": imageData(part.ImageURL.URL), + }, + }) + default: + return nil, errors.New("anthropic-messages: unsupported content part " + part.Type) + } + } + if len(content) == 0 { + return nil, errors.New("anthropic-messages: user message has no content") + } + return content, nil +} + +// messagesOnce performs one Messages streaming attempt, parsed from SSE. +func (c *Client) messagesOnce(ctx context.Context, body []byte, onText, onThink func(string), onToolCall func(id, name, args string)) (Message, Usage, error) { + hr, err := http.NewRequestWithContext(ctx, http.MethodPost, c.BaseURL+anthropicMessagesPath, strings.NewReader(string(body))) + if err != nil { + return Message{}, Usage{}, err + } + hr.Header.Set("Content-Type", "application/json") + if c.APIKey != "" { + // Bearer is the gateway's auth (inference.net validates it before + // dispatching to the Anthropic backend); x-api-key is the native + // Anthropic header, harmless for gateways that ignore it and + // required by endpoints that speak Anthropic directly. + hr.Header.Set("Authorization", "Bearer "+c.APIKey) + hr.Header.Set("x-api-key", c.APIKey) + } + hr.Header.Set("anthropic-version", "2023-06-01") + resp, err := c.do(hr, c.stallTimeout(chatStall)) + if err != nil { + return Message{}, Usage{}, err + } + defer func() { _ = resp.Body.Close() }() + if resp.StatusCode != http.StatusOK { + usage, err := responseError(resp) + return Message{}, usage, err + } + return parseMessagesSSE(resp.Body, onText, onThink, onToolCall) +} + +// parseMessagesSSE reduces an Anthropic event stream to the same callbacks +// as streamOnce: text deltas, thinking deltas (unused slice 1), tool-call +// argument accumulation keyed by block index. +func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func(id, name, args string)) (Message, Usage, error) { + msg := Message{Role: "assistant"} + sc := bufio.NewScanner(r) + sc.Buffer(make([]byte, 0, 64*1024), maxResponseBytes) + calls := map[int]*ToolCall{} + thinkingBlocks := map[int]*ThinkingBlock{} + finish := "" + done := false + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + if !strings.HasPrefix(line, "data:") { + continue + } + payload := strings.TrimPrefix(line, "data:") + var ev struct { + Type string `json:"type"` + Delta struct { + Type string `json:"type"` + Text string `json:"text"` + Thinking string `json:"thinking"` + Signature string `json:"signature"` + Partial string `json:"partial_json"` + StopReason string `json:"stop_reason"` + } `json:"delta"` + Usage struct { + InputTokens int `json:"input_tokens"` + OutputTokens int `json:"output_tokens"` + } `json:"usage"` + ContentBlock struct { + Type string `json:"type"` + ID string `json:"id"` + Name string `json:"name"` + Signature string `json:"signature"` + } `json:"content_block"` + Index int `json:"index"` + Error *struct { + Type string `json:"type"` + Message string `json:"message"` + } `json:"error"` + } + if json.Unmarshal([]byte(strings.TrimSpace(payload)), &ev) != nil { + continue + } + switch ev.Type { + case "message_start": + msg.Usage = nil + case "content_block_start": + switch ev.ContentBlock.Type { + case "tool_use": + if calls[ev.Index] == nil { + call := &ToolCall{Type: "function", ID: ev.ContentBlock.ID} + call.Function.Name = ev.ContentBlock.Name + calls[ev.Index] = call + } + case "thinking", "redacted_thinking": + if thinkingBlocks[ev.Index] == nil { + thinkingBlocks[ev.Index] = &ThinkingBlock{ + Signature: ev.ContentBlock.Signature, + // redacted blocks carry no readable thinking text + Thinking: "", + } + } + } + case "content_block_delta": + switch ev.Delta.Type { + case "text_delta": + msg.Content += ev.Delta.Text + if onText != nil { + onText(ev.Delta.Text) + } + case "thinking_delta": + if thinkingBlocks[ev.Index] == nil { + thinkingBlocks[ev.Index] = &ThinkingBlock{} + } + thinkingBlocks[ev.Index].Thinking += ev.Delta.Thinking + if onThink != nil { + onThink(ev.Delta.Thinking) + } + case "signature_delta": + if thinkingBlocks[ev.Index] == nil { + thinkingBlocks[ev.Index] = &ThinkingBlock{} + } + thinkingBlocks[ev.Index].Signature += ev.Delta.Signature + case "input_json_delta": + call := calls[ev.Index] + if call == nil { + continue + } + call.Function.Arguments += ev.Delta.Partial + if onToolCall != nil { + onToolCall(call.ID, call.Function.Name, call.Function.Arguments) + } + } + case "message_delta": + if ev.Delta.StopReason != "" { + finish = ev.Delta.StopReason + } + msg.Usage = nil + case "message_stop": + done = true + case "error": + if ev.Error != nil { + return msg, Usage{}, providerError(ev.Error.Message, msg.Content != "" || len(calls) > 0) + } + } + } + if err := sc.Err(); err != nil { + return msg, Usage{}, err + } + if finish == "" && !done { + return msg, Usage{}, errors.New("model stream ended without a completion marker") + } + // Ordered blocks: thinking indexes precede tool_use indexes for a + // thinking-enabled tool round, preserving the pairing Anthropic validates + // on replay. Iterate up to the max index seen; nil entries simply skip. + maxIndex := 0 + for i := range calls { + if i > maxIndex { + maxIndex = i + } + } + for i := range thinkingBlocks { + if i > maxIndex { + maxIndex = i + } + } + for i := 0; i <= maxIndex; i++ { + if block := thinkingBlocks[i]; block != nil { + msg.Thinking = append(msg.Thinking, *block) + } + if call := calls[i]; call != nil { + msg.ToolCalls = append(msg.ToolCalls, *call) + } + } + if finish == "max_tokens" { + msg.ToolCalls = nil + msg.Content += "\n[response truncated by max_tokens; tool calls discarded]" + } + return msg, Usage{}, nil +} diff --git a/internal/llm/messages_test.go b/internal/llm/messages_test.go new file mode 100644 index 000000000..f0d33ed59 --- /dev/null +++ b/internal/llm/messages_test.go @@ -0,0 +1,374 @@ +package llm + +import ( + "encoding/json" + "io" + "net/http" + "strings" + "testing" +) + +type rtFunc func(*http.Request) (*http.Response, error) + +func (f rtFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } + +// sse builds an Anthropic event stream from event objects, marshaled here so +// fixtures stay valid JSON by construction. +func sse(events ...any) string { + lines := make([]string, 0, len(events)+1) + for _, event := range events { + encoded, err := json.Marshal(event) + if err != nil { + panic(err) + } + lines = append(lines, "data: "+string(encoded)) + } + lines = append(lines, "") + return strings.Join(lines, "\n") +} + +func sseResponse(events ...any) *http.Response { + return &http.Response{StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(sse(events...)))} +} + +func event(kind string, fields map[string]any) map[string]any { + event := map[string]any{"type": kind} + for key, value := range fields { + event[key] = value + } + return event +} + +func TestEncodeMessagesBasics(t *testing.T) { + tool := NewTool("calc", "Evaluate arithmetic", `{"type":"object","properties":{"expr":{"type":"string"}}}`) + req := Request{ + Model: "claude-opus-5-5", + Messages: []Message{ + {Role: "system", Content: "You are whip."}, + {Role: "user", Content: "What is 6*7? Use the calc tool."}, + }, + Tools: []Tool{tool}, + MaxTokens: 1024, + } + body, err := encodeMessages(req) + if err != nil { + t.Fatal(err) + } + var decoded map[string]any + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + if decoded["system"] != "You are whip." { + t.Fatalf("system not hoisted: %s", body) + } + if decoded["max_tokens"] != float64(1024) { + t.Fatalf("max_tokens missing: %s", body) + } + if decoded["anthropic_version"] != "2023-06-01" { + t.Fatalf("version field missing: %s", body) + } + msgs := decoded["messages"].([]any) + if len(msgs) != 1 || msgs[0].(map[string]any)["role"] != "user" { + t.Fatalf("unexpected messages: %s", body) + } + tools := decoded["tools"].([]any) + if tools[0].(map[string]any)["name"] != "calc" { + t.Fatalf("tool name not anthropic shape: %s", body) + } + if _, exists := decoded["prompt_cache_key"]; exists { + t.Fatal("chat-only prompt_cache_key leaked into messages request") + } +} + +func TestEncodeMessagesToolRoundTrip(t *testing.T) { + // The exact history shape that 400s through the chat translator: an + // assistant tool-call turn (empty content) followed by a tool result. + // Natively this encodes to tool_use + tool_result blocks cleanly. + var call ToolCall + call.ID, call.Type = "toolu_1", "function" + call.Function.Name, call.Function.Arguments = "calc", `{"expr":"6*7"}` + req := Request{ + Model: "claude-opus-5-5", + Messages: []Message{ + {Role: "user", Content: "What is 6*7?"}, + {Role: "assistant", ToolCalls: []ToolCall{call}}, + {Role: "tool", ToolCallID: "toolu_1", Name: "calc", Content: "42"}, + }, + } + body, err := encodeMessages(req) + if err != nil { + t.Fatal(err) + } + var decoded struct { + Messages []struct { + Role string `json:"role"` + Content []struct { + Type string `json:"type"` + ID string `json:"id"` + ToolUseID string `json:"tool_use_id"` + Input map[string]any `json:"input"` + } `json:"content"` + } `json:"messages"` + } + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + if len(decoded.Messages) != 3 { + t.Fatalf("expected 3 messages, got %d: %s", len(decoded.Messages), body) + } + assistant := decoded.Messages[1] + if assistant.Role != "assistant" || len(assistant.Content) != 1 || assistant.Content[0].Type != "tool_use" { + t.Fatalf("assistant tool_use not encoded: %s", body) + } + if assistant.Content[0].Input["expr"] != "6*7" { + t.Fatalf("tool input not decoded from arguments: %s", body) + } + result := decoded.Messages[2] + if result.Role != "user" || result.Content[0].Type != "tool_result" || result.Content[0].ToolUseID != "toolu_1" { + t.Fatalf("tool_result not encoded as user role: %s", body) + } +} + +func TestEncodeMessagesThinkingBudget(t *testing.T) { + // Effort maps to thinking.budget_tokens; the budget always leaves room + // for visible output below the max_tokens ceiling. + for effort, want := range map[string]int{"low": 2048, "medium": 4096, "high": 4096 /* capped by maxTokens/2 */, "max": 4096 /* capped by maxTokens/2 */} { + req := Request{Model: "claude-opus-5-5", ReasoningEffort: effort, MaxTokens: 8192} + body, err := encodeMessages(req) + if err != nil { + t.Fatalf("%s: %v", effort, err) + } + var decoded struct { + Thinking struct { + Type string `json:"type"` + BudgetTokens int `json:"budget_tokens"` + } `json:"thinking"` + } + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + if decoded.Thinking.Type != "enabled" || decoded.Thinking.BudgetTokens != want { + t.Fatalf("%s: thinking = %+v, want enabled/%d", effort, decoded.Thinking, want) + } + } + // Known off-levels omit thinking entirely. + for _, off := range []string{"", "off", "none"} { + req := Request{Model: "claude-opus-5-5", ReasoningEffort: off, MaxTokens: 1024} + body, err := encodeMessages(req) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(body), `"thinking"`) { + t.Fatalf("effort %q must not enable thinking: %s", off, body) + } + } + // Unknown levels fail loudly rather than guess a budget. + if _, err := encodeMessages(Request{Model: "x", ReasoningEffort: "ultra"}); err == nil { + t.Fatal("expected error for unknown effort level") + } +} + +func TestEncodeMessagesReplaysThinkingBeforeToolUse(t *testing.T) { + var call ToolCall + call.ID, call.Type = "toolu_1", "function" + call.Function.Name, call.Function.Arguments = "calc", `{"expr":"6*7"}` + req := Request{ + Model: "claude-opus-5-5", + Messages: []Message{{ + Role: "assistant", + Thinking: []ThinkingBlock{{Thinking: "hmm", Signature: "sig-abc"}}, + ToolCalls: []ToolCall{call}, + }}, + } + body, err := encodeMessages(req) + if err != nil { + t.Fatal(err) + } + var decoded struct { + Messages []struct { + Content []struct { + Type string `json:"type"` + Thinking string `json:"thinking"` + Signature string `json:"signature"` + } `json:"content"` + } `json:"messages"` + } + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + blocks := decoded.Messages[0].Content + if len(blocks) < 2 || blocks[0].Type != "thinking" || blocks[0].Signature != "sig-abc" || blocks[1].Type != "tool_use" { + t.Fatalf("thinking must precede tool_use with signature verbatim: %s", body) + } +} + +func TestParseMessagesSSECapturesThinkingSignature(t *testing.T) { + stream := sse( + event("message_start", nil), + event("content_block_start", map[string]any{"index": 0, "content_block": map[string]any{"type": "thinking"}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "thinking_delta", "thinking": "rea"}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "thinking_delta", "thinking": "soning"}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "signature_delta", "signature": "sig-123"}}), + event("content_block_start", map[string]any{"index": 1, "content_block": map[string]any{"type": "tool_use", "id": "toolu_2", "name": "calc"}}), + event("content_block_delta", map[string]any{"index": 1, "delta": map[string]any{"type": "input_json_delta", "partial_json": `{}`}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "tool_use"}}), + event("message_stop", nil), + ) + var thought string + msg, _, err := parseMessagesSSE(strings.NewReader(stream), nil, func(s string) { thought += s }, nil) + if err != nil { + t.Fatal(err) + } + if thought != "reasoning" { + t.Fatalf("onThink stream: %q", thought) + } + if len(msg.Thinking) != 1 || msg.Thinking[0].Thinking != "reasoning" || msg.Thinking[0].Signature != "sig-123" { + t.Fatalf("captured thinking: %+v", msg.Thinking) + } + if len(msg.ToolCalls) != 1 { + t.Fatalf("tool calls: %+v", msg.ToolCalls) + } +} + +func TestChatEncodeClearsThinking(t *testing.T) { + // Chat-completions has no thinking shape; captured blocks must not leak. + client := New("https://api.inference.net/v1", "key") + msgs := []Message{{Role: "assistant", Thinking: []ThinkingBlock{{Thinking: "x", Signature: "y"}}}} + req := Request{Model: "claude-opus-5-5", Messages: msgs} + body, err := client.encodeChatRequest(req) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(body), "signature") || strings.Contains(string(body), "sig") { + t.Fatalf("thinking leaked into chat request: %s", body) + } + if len(msgs[0].Thinking) == 0 { + t.Fatal("encodeChatRequest must not mutate the caller's history") + } +} + +func TestMessageThinkingRoundTripsThroughJSON(t *testing.T) { + // Persisted session compat: old sessions decode with no thinking; new + // ones keep the signature verbatim across marshal/unmarshal. + encoded, err := json.Marshal(Message{Role: "assistant", Thinking: []ThinkingBlock{{Thinking: "t", Signature: "s"}}}) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(encoded), `"signature":"s"`) { + t.Fatalf("signature not persisted: %s", encoded) + } + var decoded Message + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatal(err) + } + if len(decoded.Thinking) != 1 || decoded.Thinking[0].Signature != "s" { + t.Fatalf("round trip: %+v", decoded.Thinking) + } + var legacy Message + if err := json.Unmarshal([]byte(`{"role":"assistant","content":"old"}`), &legacy); err != nil { + t.Fatal(err) + } + if legacy.Thinking != nil { + t.Fatal("legacy messages must decode with nil thinking") + } +} + +func TestParseMessagesSSE(t *testing.T) { + stream := sse( + event("message_start", map[string]any{"usage": map[string]any{"input_tokens": 10}}), + event("content_block_start", map[string]any{"index": 0, "content_block": map[string]any{"type": "tool_use", "id": "toolu_1", "name": "calc"}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "input_json_delta", "partial_json": `{"expr"`}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "input_json_delta", "partial_json": `:"6*7"}`}}), + event("content_block_start", map[string]any{"index": 1, "content_block": map[string]any{"type": "text"}}), + event("content_block_delta", map[string]any{"index": 1, "delta": map[string]any{"type": "text_delta", "text": "Done."}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "tool_use"}}), + event("message_stop", nil), + ) + var toolArgs string + msg, _, err := parseMessagesSSE(strings.NewReader(stream), nil, nil, func(id, name, args string) { + toolArgs = args + }) + if err != nil { + t.Fatal(err) + } + if msg.Content != "Done." { + t.Fatalf("text: %q", msg.Content) + } + if len(msg.ToolCalls) != 1 || msg.ToolCalls[0].ID != "toolu_1" || msg.ToolCalls[0].Function.Name != "calc" { + t.Fatalf("tool calls: %+v", msg.ToolCalls) + } + if toolArgs != `{"expr":"6*7"}` { + t.Fatalf("streamed args: %q", toolArgs) + } +} + +func TestMessagesClientTargetsMessagesEndpoint(t *testing.T) { + var gotPath string + client := NewMessagesClient("https://api.inference.net/v1", "key") + client.HTTP = &http.Client{Transport: rtFunc(func(r *http.Request) (*http.Response, error) { + gotPath = r.URL.Path + if r.Header.Get("x-api-key") != "key" { + t.Fatal("missing x-api-key header") + } + if r.Header.Get("anthropic-version") == "" { + t.Fatal("missing anthropic-version header") + } + return sseResponse( + event("message_start", nil), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "text_delta", "text": "hi"}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "end_turn"}}), + event("message_stop", nil), + ), nil + })} + msg, _, err := client.messagesOnce(t.Context(), []byte(`{}`), nil, nil, nil) + if err != nil { + t.Fatal(err) + } + if gotPath != "/v1/messages" { + t.Fatalf("posted to %s, want /v1/messages", gotPath) + } + if msg.Content != "hi" { + t.Fatalf("content: %q", msg.Content) + } +} + +func TestMessagesStreamDispatchRoundTrip(t *testing.T) { + // End to end through Stream's dispatch + retry machinery on the messages + // flavor: encode, route to /messages, parse, accumulate tool calls. + firstCall := true + client := NewMessagesClient("https://api.example.test/v1", "key") + client.HTTP = &http.Client{Transport: rtFunc(func(r *http.Request) (*http.Response, error) { + if r.URL.Path != "/v1/messages" { + t.Fatalf("posted to %s, want /v1/messages", r.URL.Path) + } + if firstCall { + firstCall = false + return sseResponse( + event("message_start", nil), + event("content_block_start", map[string]any{"index": 0, "content_block": map[string]any{"type": "tool_use", "id": "toolu_9", "name": "calc"}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "input_json_delta", "partial_json": `{"expr":"2+2"}`}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "tool_use"}}), + event("message_stop", nil), + ), nil + } + return sseResponse( + event("message_start", nil), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "text_delta", "text": "4"}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "end_turn"}}), + event("message_stop", nil), + ), nil + })} + req := Request{ + Model: "claude-opus-5-5", + Messages: []Message{{Role: "user", Content: "2+2 use calc"}}, + Tools: []Tool{NewTool("calc", "arithmetic", `{"type":"object"}`)}, + MaxTokens: 128, + } + first, _, err := client.Stream(t.Context(), req, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + if len(first.ToolCalls) != 1 || first.ToolCalls[0].ID != "toolu_9" { + t.Fatalf("first round tool calls: %+v", first.ToolCalls) + } +} diff --git a/internal/llm/openai.go b/internal/llm/openai.go index 9ac2d245b..c2e6bfe5f 100644 --- a/internal/llm/openai.go +++ b/internal/llm/openai.go @@ -58,6 +58,12 @@ type Message struct { // provider"), so a /model switch mid-session doesn't rewrite history // silently. Internal only — never sent to the provider. Model string `json:"model,omitempty"` + // Thinking carries the assistant's thinking blocks for models that + // support extended thinking (Anthropic Messages flavor). Captured from + // the provider stream and replayed with tool_use — Anthropic validates + // the pairing, so a thinking-enabled tool round cannot be replayed + // without it. Empty for other providers and older sessions. + Thinking []ThinkingBlock `json:"-"` // RewoundFrom notes that this message replaced an earlier clipped one // (rewind + resubmit). Internal only — never sent to the provider. RewoundFrom string `json:"rewound_from,omitempty"` @@ -149,6 +155,14 @@ func (p ContentPart) DecodeDimensions() (w, h int, ok bool) { return DecodeImageSize(head) } +// ThinkingBlock is one captured thinking block from an Anthropic Messages +// stream: the visible text and the opaque signature that must be replayed +// verbatim with tool_use turns. +type ThinkingBlock struct { + Thinking string `json:"thinking"` + Signature string `json:"signature"` +} + // messageWire is the JSON shape of a Message. Content is `any` so it can be a // plain string (text-only) or a []ContentPart array (multimodal). The internal // fields are omitempty and cleared by stripAuthored before a provider request, @@ -167,6 +181,7 @@ type messageWire struct { Model string `json:"model,omitempty"` RewoundFrom string `json:"rewound_from,omitempty"` CallID string `json:"call_id,omitempty"` + Thinking []ThinkingBlock `json:"thinking,omitempty"` } // MarshalJSON sends Content as a plain string for text-only messages and as a @@ -176,7 +191,7 @@ func (m Message) MarshalJSON() ([]byte, error) { Continuation: m.Continuation, Presentation: m.Presentation, Role: m.Role, Content: m.Content, ToolCalls: m.ToolCalls, ToolCallID: m.ToolCallID, Name: m.Name, Authored: m.Authored, SentAt: m.SentAt, Usage: m.Usage, - Model: m.Model, RewoundFrom: m.RewoundFrom, CallID: m.CallID, + Model: m.Model, RewoundFrom: m.RewoundFrom, CallID: m.CallID, Thinking: m.Thinking, } if len(m.Parts) > 0 { parts := m.Parts @@ -203,6 +218,7 @@ func (m *Message) UnmarshalJSON(data []byte) error { m.Presentation = raw.Presentation m.Role, m.ToolCalls, m.ToolCallID, m.Name = raw.Role, raw.ToolCalls, raw.ToolCallID, raw.Name m.Authored, m.SentAt, m.Usage, m.Model, m.RewoundFrom, m.CallID = raw.Authored, raw.SentAt, raw.Usage, raw.Model, raw.RewoundFrom, raw.CallID + m.Thinking = raw.Thinking if len(raw.Content) == 0 { return nil } @@ -388,7 +404,12 @@ type Client struct { openAI *openaiauth.Manager BaseURL string APIKey string - HTTP *http.Client + // Flavor selects the wire protocol: FlavorChat (default) posts + // chat-completions; FlavorMessages speaks Anthropic Messages natively + // (encodeMessages / messagesOnce). Config sets it from the provider's + // "api" value; it never changes for the life of the client. + Flavor APIFlavor + HTTP *http.Client // MaxRetries caps retries of transient request failures. 0 uses // DefaultMaxAttempts; 1 disables retries (a single attempt). MaxRetries int @@ -430,6 +451,25 @@ func New(baseURL, apiKey string) *Client { } } +// APIFlavor is the wire protocol a Client speaks. +type APIFlavor int + +const ( + // FlavorChat posts OpenAI-compatible chat-completions (the default). + FlavorChat APIFlavor = iota + // FlavorMessages speaks Anthropic Messages natively: requests encode via + // encodeMessages to {BaseURL}/messages and responses parse from the + // Anthropic SSE event stream. Providers whose Claude style models list a + // "messages" endpoint (inference.net) use this flavor. + FlavorMessages +) + +// NewMessagesClient returns a Client speaking the Anthropic Messages protocol +// / to baseURL (its /messages endpoint). +func NewMessagesClient(baseURL, apiKey string) *Client { + return &Client{BaseURL: strings.TrimRight(baseURL, "/"), APIKey: apiKey, Flavor: FlavorMessages, HTTP: &http.Client{}} +} + // Request is a chat completions request. type Request struct { // OutputLimitExplicit distinguishes a caller's hard output cap from an @@ -873,6 +913,9 @@ func (c *Client) streamOnce(ctx context.Context, body []byte, onText, onThink fu if c.openAI != nil { return c.subscriptionOnce(ctx, body, onText, onThink, onToolCall) } + if c.Flavor == FlavorMessages { + return c.messagesOnce(ctx, body, onText, onThink, onToolCall) + } hr, err := httpRequest(ctx, c.BaseURL, body) if err != nil { return Message{}, Usage{}, err @@ -1099,6 +1142,23 @@ func (c *Client) completeOnce(ctx context.Context, body []byte) (string, Usage, return text, usage, nil } +// newRequest builds the flavor-appropriate HTTP request: /messages for the +// Messages flavor, /chat/completions otherwise. Validation duplicates +// httpRequest's scheme/host check. +func (c *Client) newRequest(ctx context.Context, body []byte) (*http.Request, error) { + if c.Flavor == FlavorMessages { + request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.BaseURL+anthropicMessagesPath, bytes.NewReader(body)) + if err != nil { + return nil, err + } + if (request.URL.Scheme != "http" && request.URL.Scheme != "https") || request.URL.Host == "" { + return nil, errors.New("invalid model provider URL") + } + return request, nil + } + return httpRequest(ctx, c.BaseURL, body) +} + func httpRequest(ctx context.Context, baseURL string, body []byte) (*http.Request, error) { request, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+"/chat/completions", bytes.NewReader(body)) if err != nil { diff --git a/internal/llm/provider_compatibility.go b/internal/llm/provider_compatibility.go index d9acdcd90..406d34c6b 100644 --- a/internal/llm/provider_compatibility.go +++ b/internal/llm/provider_compatibility.go @@ -7,12 +7,34 @@ import ( // encodeChatRequest limits provider-specific changes to exact preset roots. // A custom proxy keeps the generic wire contract, even with a familiar hostname. +func hasThinking(msgs []Message) bool { + for _, m := range msgs { + if len(m.Thinking) > 0 { + return true + } + } + return false +} + func (c *Client) encodeChatRequest(req Request) ([]byte, error) { // "off" is the explicit no-reasoning level everywhere else in whip; the // wire contract expresses it by omitting the parameter. if req.ReasoningEffort == "off" { req.ReasoningEffort = "" } + // Chat-completions has no thinking-block shape; replaying captured + // Anthropic thinking there is at best ignored and at worst a strict + // provider's rejection. Only the messages flavor replays thinking. + // req.Messages aliases the caller's conversation slice — copy first so + // the captured thinking survives in storage. + if hasThinking(req.Messages) { + msgs := make([]Message, len(req.Messages)) + copy(msgs, req.Messages) + for i := range msgs { + msgs[i].Thinking = nil + } + req.Messages = msgs + } switch c.BaseURL { case "https://api.cerebras.ai/v1", "https://api.groq.com/openai/v1", "https://api.deepseek.com", "https://api.fireworks.ai/inference/v1", "https://api.together.ai/v1", "https://api.deepinfra.com/v1/openai": From 17771cdf45dae561e3b7e33f9d3836d99d1b4c4b Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Mon, 28 Sep 2026 17:00:54 -0700 Subject: [PATCH 13/67] fix(llm): resolve golangci-lint findings on messages flavor - rename shadowed predeclared cap -> budgetTokens (predeclared) - replace manual map loop with maps.Copy (modernize) - align struct literal fields (gofumpt) - use canonical header names X-Api-Key / Anthropic-Version in Set/Get calls (canonicalheader); behavior unchanged since net/http canonicalizes keys regardless --- internal/llm/messages.go | 8 ++++---- internal/llm/messages_test.go | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/internal/llm/messages.go b/internal/llm/messages.go index 248d44ced..b27b725db 100644 --- a/internal/llm/messages.go +++ b/internal/llm/messages.go @@ -65,10 +65,10 @@ func encodeMessages(req Request) ([]byte, error) { thinkingEnabled := req.ReasoningEffort != "" && req.ReasoningEffort != "off" && req.ReasoningEffort != "none" budget := 0 if thinkingEnabled { - if cap, ok := thinkingBudgetTokens[req.ReasoningEffort]; ok { + if budgetTokens, ok := thinkingBudgetTokens[req.ReasoningEffort]; ok { // Anthropic requires max_tokens > budget_tokens; leave room for // visible output by capping the budget at half the ceiling. - budget = min(cap, maxTokens/2) + budget = min(budgetTokens, maxTokens/2) } else { // Unknown effort level: a wrong budget is a hard 400 upstream. // Fail loudly rather than guess. @@ -207,9 +207,9 @@ func (c *Client) messagesOnce(ctx context.Context, body []byte, onText, onThink // Anthropic header, harmless for gateways that ignore it and // required by endpoints that speak Anthropic directly. hr.Header.Set("Authorization", "Bearer "+c.APIKey) - hr.Header.Set("x-api-key", c.APIKey) + hr.Header.Set("X-Api-Key", c.APIKey) } - hr.Header.Set("anthropic-version", "2023-06-01") + hr.Header.Set("Anthropic-Version", "2023-06-01") resp, err := c.do(hr, c.stallTimeout(chatStall)) if err != nil { return Message{}, Usage{}, err diff --git a/internal/llm/messages_test.go b/internal/llm/messages_test.go index f0d33ed59..4cc09e85d 100644 --- a/internal/llm/messages_test.go +++ b/internal/llm/messages_test.go @@ -3,6 +3,7 @@ package llm import ( "encoding/json" "io" + "maps" "net/http" "strings" "testing" @@ -33,9 +34,7 @@ func sseResponse(events ...any) *http.Response { func event(kind string, fields map[string]any) map[string]any { event := map[string]any{"type": kind} - for key, value := range fields { - event[key] = value - } + maps.Copy(event, fields) return event } @@ -175,8 +174,8 @@ func TestEncodeMessagesReplaysThinkingBeforeToolUse(t *testing.T) { req := Request{ Model: "claude-opus-5-5", Messages: []Message{{ - Role: "assistant", - Thinking: []ThinkingBlock{{Thinking: "hmm", Signature: "sig-abc"}}, + Role: "assistant", + Thinking: []ThinkingBlock{{Thinking: "hmm", Signature: "sig-abc"}}, ToolCalls: []ToolCall{call}, }}, } @@ -307,11 +306,11 @@ func TestMessagesClientTargetsMessagesEndpoint(t *testing.T) { client := NewMessagesClient("https://api.inference.net/v1", "key") client.HTTP = &http.Client{Transport: rtFunc(func(r *http.Request) (*http.Response, error) { gotPath = r.URL.Path - if r.Header.Get("x-api-key") != "key" { - t.Fatal("missing x-api-key header") + if r.Header.Get("X-Api-Key") != "key" { + t.Fatal("missing X-Api-Key header") } - if r.Header.Get("anthropic-version") == "" { - t.Fatal("missing anthropic-version header") + if r.Header.Get("Anthropic-Version") == "" { + t.Fatal("missing Anthropic-Version header") } return sseResponse( event("message_start", nil), From d24fcb94e2b01c76c62c2d046c0a9920a2cb8b08 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Mon, 28 Sep 2026 17:11:14 -0700 Subject: [PATCH 14/67] fix(llm): address Bugbot review findings on messages flavor 1. Parallel tool results (High): consecutive tool-role messages were each emitted as separate user turns; Anthropic requires all tool_result blocks for one assistant turn inside a single user message. Merge them before flushing on the next non-tool role. 2. Complete ignores Messages flavor (High): Complete posted a non-streaming request to /chat/completions even on the messages flavor, where encodeMessages always sets stream:true. Route FlavorMessages through Stream with nil callbacks instead, matching the responses/openAI path. 3. Messages stream drops usage (Medium): parseMessagesSSE read input_tokens (message_start) and output_tokens (message_delta) but always returned Usage{}. Capture both and return a populated Usage so token counts, cost display, and budget settlement work. Read message_start usage from the nested message.usage field. 4. Thinking budget equals max tokens (Medium): the 1024 budget floor could meet or exceed max_tokens on small calls, which Anthropic rejects. Bump max_tokens above the budget when needed, and always include max_tokens when thinking is enabled (Anthropic requires the field even when MaxTokens was zero). Add tests for each fix: merged parallel results, usage reporting from SSE, and budget-below-max-tokens across small/zero MaxTokens values. --- internal/llm/messages.go | 51 ++++++++++++---- internal/llm/messages_test.go | 106 ++++++++++++++++++++++++++++++++++ internal/llm/openai.go | 5 +- 3 files changed, 151 insertions(+), 11 deletions(-) diff --git a/internal/llm/messages.go b/internal/llm/messages.go index b27b725db..6978a106e 100644 --- a/internal/llm/messages.go +++ b/internal/llm/messages.go @@ -75,13 +75,32 @@ func encodeMessages(req Request) ([]byte, error) { return nil, fmt.Errorf("anthropic-messages: unsupported reasoning effort %q", req.ReasoningEffort) } budget = max(budget, 1024) // documented minimum + // Anthropic requires max_tokens > budget_tokens; ensure the + // ceiling clears the floor even on small max_tokens calls. + if maxTokens <= budget { + maxTokens = budget + 1 + } } // When thinking is on but history carries no thinking blocks (sessions // predating capture, or the turn itself), Anthropic still accepts the // request — thinking need only be replayed once emitted.. var system []string blocks := []any{} + // Anthropic requires all parallel tool_result blocks inside a single + // user message. Consecutive tool-role entries in whip history (the + // result of one assistant turn calling multiple tools) must be merged + // before the next non-tool message flushes the batch. + flushToolResults := func(results []any) { + if len(results) > 0 { + blocks = append(blocks, map[string]any{"role": "user", "content": results}) + } + } + var toolResults []any for _, message := range req.Messages { + if message.Role != "tool" { + flushToolResults(toolResults) + toolResults = nil + } switch message.Role { case "system", "developer": system = append(system, message.TextContent()) @@ -115,16 +134,14 @@ func encodeMessages(req Request) ([]byte, error) { } blocks = append(blocks, map[string]any{"role": "assistant", "content": content}) case "tool": - blocks = append(blocks, map[string]any{ - "role": "user", - "content": []any{map[string]any{ - "type": "tool_result", "tool_use_id": message.ToolCallID, "content": message.TextContent(), - }}, + toolResults = append(toolResults, map[string]any{ + "type": "tool_result", "tool_use_id": message.ToolCallID, "content": message.TextContent(), }) default: return nil, fmt.Errorf("anthropic-messages: unsupported message role %q", message.Role) } } + flushToolResults(toolResults) var tools []any for _, tool := range req.Tools { var schema any @@ -145,8 +162,8 @@ func encodeMessages(req Request) ([]byte, error) { if len(tools) > 0 { body["tools"] = tools } - if req.MaxTokens > 0 { - body["max_tokens"] = req.MaxTokens + if req.MaxTokens > 0 || thinkingEnabled { + body["max_tokens"] = maxTokens } if req.Temperature != nil { body["temperature"] = *req.Temperature @@ -233,6 +250,8 @@ func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func thinkingBlocks := map[int]*ThinkingBlock{} finish := "" done := false + inputTokens := 0 + outputTokens := 0 for sc.Scan() { line := strings.TrimSpace(sc.Text()) if !strings.HasPrefix(line, "data:") { @@ -259,6 +278,14 @@ func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func Name string `json:"name"` Signature string `json:"signature"` } `json:"content_block"` + // message_start nests usage under message.usage; message_delta + // carries usage at the event root. + Message struct { + Usage struct { + InputTokens int `json:"input_tokens"` + OutputTokens int `json:"output_tokens"` + } `json:"usage"` + } `json:"message"` Index int `json:"index"` Error *struct { Type string `json:"type"` @@ -270,7 +297,7 @@ func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func } switch ev.Type { case "message_start": - msg.Usage = nil + inputTokens = ev.Message.Usage.InputTokens case "content_block_start": switch ev.ContentBlock.Type { case "tool_use": @@ -322,7 +349,9 @@ func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func if ev.Delta.StopReason != "" { finish = ev.Delta.StopReason } - msg.Usage = nil + if ev.Usage.OutputTokens > 0 { + outputTokens = ev.Usage.OutputTokens + } case "message_stop": done = true case "error": @@ -363,5 +392,7 @@ func parseMessagesSSE(r io.Reader, onText, onThink func(string), onToolCall func msg.ToolCalls = nil msg.Content += "\n[response truncated by max_tokens; tool calls discarded]" } - return msg, Usage{}, nil + usage := Usage{PromptTokens: inputTokens, CompletionTokens: outputTokens} + usage.Reported = usage.HasUsage() + return msg, usage, nil } diff --git a/internal/llm/messages_test.go b/internal/llm/messages_test.go index 4cc09e85d..b7d4a420b 100644 --- a/internal/llm/messages_test.go +++ b/internal/llm/messages_test.go @@ -371,3 +371,109 @@ func TestMessagesStreamDispatchRoundTrip(t *testing.T) { t.Fatalf("first round tool calls: %+v", first.ToolCalls) } } + +func TestEncodeMessagesMergesParallelToolResults(t *testing.T) { + // Two tool results from one assistant turn must land in a single user + // message with two tool_result blocks; Anthropic rejects consecutive + // user turns for parallel results. + var callA, callB ToolCall + callA.ID, callA.Type = "toolu_1", "function" + callA.Function.Name, callA.Function.Arguments = "calc", `{"expr":"6*7"}` + callB.ID, callB.Type = "toolu_2", "function" + callB.Function.Name, callB.Function.Arguments = "calc", `{"expr":"2+2"}` + req := Request{ + Model: "claude-opus-5-5", + Messages: []Message{ + {Role: "user", Content: "compute both"}, + {Role: "assistant", ToolCalls: []ToolCall{callA, callB}}, + {Role: "tool", ToolCallID: "toolu_1", Content: "42"}, + {Role: "tool", ToolCallID: "toolu_2", Content: "4"}, + }, + } + body, err := encodeMessages(req) + if err != nil { + t.Fatal(err) + } + var decoded struct { + Messages []struct { + Role string `json:"role"` + Content []struct { + Type string `json:"type"` + ToolUseID string `json:"tool_use_id"` + } `json:"content"` + } `json:"messages"` + } + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + // user, assistant, merged-results = 3 messages (not 4). + if len(decoded.Messages) != 3 { + t.Fatalf("expected 3 messages, got %d: %s", len(decoded.Messages), body) + } + results := decoded.Messages[2] + if results.Role != "user" { + t.Fatalf("merged results role: %s, want user", results.Role) + } + if len(results.Content) != 2 { + t.Fatalf("expected 2 tool_result blocks, got %d: %s", len(results.Content), body) + } + if results.Content[0].Type != "tool_result" || results.Content[0].ToolUseID != "toolu_1" { + t.Fatalf("first result: %+v", results.Content[0]) + } + if results.Content[1].Type != "tool_result" || results.Content[1].ToolUseID != "toolu_2" { + t.Fatalf("second result: %+v", results.Content[1]) + } +} + +func TestParseMessagesSSEReportsUsage(t *testing.T) { + // message_start carries input_tokens under message.usage; message_delta + // carries output_tokens at the root. Both must reach the returned Usage. + stream := sse( + event("message_start", map[string]any{"message": map[string]any{"usage": map[string]any{"input_tokens": 12}}}), + event("content_block_delta", map[string]any{"index": 0, "delta": map[string]any{"type": "text_delta", "text": "hi"}}), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "end_turn"}, "usage": map[string]any{"output_tokens": 7}}), + event("message_stop", nil), + ) + _, usage, err := parseMessagesSSE(strings.NewReader(stream), nil, nil, nil) + if err != nil { + t.Fatal(err) + } + if usage.PromptTokens != 12 { + t.Fatalf("prompt tokens: %d, want 12", usage.PromptTokens) + } + if usage.CompletionTokens != 7 { + t.Fatalf("completion tokens: %d, want 7", usage.CompletionTokens) + } + if !usage.Reported { + t.Fatal("usage.Reported should be true when token counts are present") + } +} + +func TestEncodeMessagesThinkingBudgetBelowMaxTokens(t *testing.T) { + // When MaxTokens is small (2048), the 1024 budget floor must not + // collide with the ceiling. max_tokens must always exceed budget_tokens, + // and max_tokens must be present when thinking is enabled even if + // MaxTokens was zero (Anthropic requires the field). + for _, mt := range []int{0, 1024, 2048} { + req := Request{Model: "claude-opus-5-5", ReasoningEffort: "minimal", MaxTokens: mt} + body, err := encodeMessages(req) + if err != nil { + t.Fatalf("maxTokens=%d: %v", mt, err) + } + var decoded struct { + MaxTokens int `json:"max_tokens"` + Thinking struct { + BudgetTokens int `json:"budget_tokens"` + } `json:"thinking"` + } + if err := json.Unmarshal(body, &decoded); err != nil { + t.Fatal(err) + } + if decoded.MaxTokens <= decoded.Thinking.BudgetTokens { + t.Fatalf("maxTokens=%d: max_tokens %d <= budget %d", mt, decoded.MaxTokens, decoded.Thinking.BudgetTokens) + } + if decoded.MaxTokens == 0 { + t.Fatalf("maxTokens=%d: max_tokens must be present when thinking is enabled", mt) + } + } +} diff --git a/internal/llm/openai.go b/internal/llm/openai.go index c2e6bfe5f..47951ee57 100644 --- a/internal/llm/openai.go +++ b/internal/llm/openai.go @@ -1064,7 +1064,10 @@ func validToolCallArgs(s string) bool { // summary call, where streaming would just add UI noise for a one-shot // synthesis. func (c *Client) Complete(ctx context.Context, req Request) (string, Usage, error) { - if c.openAI != nil || c.apiResponses(req.Model) { + if c.openAI != nil || c.apiResponses(req.Model) || c.Flavor == FlavorMessages { + // The responses and messages flavors always stream (encodeMessages + // sets stream:true), so Complete drains the stream with nil + // callbacks rather than posting a non-streaming request. message, usage, err := c.Stream(ctx, req, nil, nil, nil) return message.Content, usage, err } From 2e490e6df64512791b5c1670065f7f2414ab99e8 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Mon, 28 Sep 2026 18:09:53 -0700 Subject: [PATCH 15/67] fix: resolve pre-existing CI failures on development branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lint (golangci-lint) — 21 issues across 6 files: - errorlint: nolint on intentional direct type assertion in compactionRejected (excludes wrapped errors by design) - nilnil: nolint on 6 return nil,nil in title.go (nil is a valid no-op signal for title initialization) - noctx: use net.ListenConfig/DialContext in title_notifications_test - perfsprint: fmt.Sprint -> strconv.Itoa/FormatBool in test files - staticcheck: convert params to ArchiveResult, copy() instead of loop, tagged switches instead of if/else-if chains - tparallel: add t.Parallel() to subtests - usestdlibvars: http.Status constants instead of string literals - usetesting: keep os.MkdirTemp (short path for macOS socket limit) with nolint directive Docs (test:docs) — 1 type error: - session.command() inferred CommandHandle<string> instead of CommandHandle<"submit">; add explicit return type CommandHandle<O> Test (TestResumeActiveIsolatesFailuresAndAllowsRetry): - open() persisted resolved Effort to store before the factory ran, so a failed restore mutated the saved session. Move SetEffort after the factory succeeds. --- internal/agent/compaction_route.go | 2 +- internal/agent/compaction_route_test.go | 15 ++++++++------- internal/daemon/control.go | 2 +- internal/daemon/daemon.go | 10 +++++++--- internal/daemon/title_notifications_test.go | 19 ++++++++++++------- internal/session/title.go | 12 ++++++------ internal/session/title_admission_test.go | 5 +++-- internal/tui/client.go | 4 +--- internal/tui/client_control_render_test.go | 1 + packages/sdk/src/session.ts | 4 ++-- 10 files changed, 42 insertions(+), 32 deletions(-) diff --git a/internal/agent/compaction_route.go b/internal/agent/compaction_route.go index c4bc7835d..d306a81ef 100644 --- a/internal/agent/compaction_route.go +++ b/internal/agent/compaction_route.go @@ -111,7 +111,7 @@ func (a *Agent) compactionSummary(ctx context.Context, messages []llm.Message, o func compactionRejected(err error) bool { // A direct HTTP rejection excludes accounting/validation wrappers even // when they contain an HTTPError. Timeouts can hide completed work. - rejection, ok := err.(*llm.HTTPError) + rejection, ok := err.(*llm.HTTPError) //nolint:errorlint // direct cast intentionally excludes wrapped errors if !ok || rejection.ResponseStarted { return false } diff --git a/internal/agent/compaction_route_test.go b/internal/agent/compaction_route_test.go index eb8b47850..a4f476336 100644 --- a/internal/agent/compaction_route_test.go +++ b/internal/agent/compaction_route_test.go @@ -9,6 +9,7 @@ import ( "net/http" "net/http/httptest" "reflect" + "strconv" "strings" "sync/atomic" "testing" @@ -192,7 +193,7 @@ func TestCompactionFallbackDoesNotHideEarlierUnknownCompletion(t *testing.T) { if custom == 1 { return nil, io.ErrUnexpectedEOF } - return &http.Response{StatusCode: 400, Status: "400 Bad Request", Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil + return &http.Response{StatusCode: http.StatusBadRequest, Status: "400 Bad Request", Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil })} _, _, _, err := a.CompactNow(t.Context()) if err == nil || custom != 2 || conversation != 0 { @@ -202,7 +203,7 @@ func TestCompactionFallbackDoesNotHideEarlierUnknownCompletion(t *testing.T) { func TestCompactionFallbackPreflightsPreparedSummaryRequest(t *testing.T) { for _, limit := range []int{100, 8192} { - t.Run(fmt.Sprint(limit), func(t *testing.T) { + t.Run(strconv.Itoa(limit), func(t *testing.T) { var requests []llm.Request a := compactionRouteAgent(t, func(w http.ResponseWriter, r *http.Request) { var request llm.Request @@ -237,7 +238,7 @@ func TestCompactionFallbackPreflightsPreparedSummaryRequest(t *testing.T) { func TestCompactionFallbackUsesSubscriptionNaturalOutputForPreflight(t *testing.T) { for _, fits := range []bool{false, true} { - t.Run(fmt.Sprint(fits), func(t *testing.T) { + t.Run(strconv.FormatBool(fits), func(t *testing.T) { var conversation, subscription int a := compactionRouteAgent(t, func(w http.ResponseWriter, _ *http.Request) { conversation++ @@ -269,7 +270,7 @@ func TestCompactionFallbackUsesSubscriptionNaturalOutputForPreflight(t *testing. t.Error("subscription request included an unsupported explicit output cap") } body := "data: {\"type\":\"response.completed\",\"response\":{\"status\":\"completed\",\"output\":[{\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"output_text\",\"text\":\"summary\"}]}]}}\n\n" - return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + return &http.Response{Status: "200 OK", StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil })} var reservation int a.SetModelCallBudget(attemptBudgetFunc(func(_ context.Context, attempt llm.ModelAttempt) (llm.ModelPermit, error) { @@ -304,9 +305,9 @@ func TestCompactionFallbackDoesNotHideRegeneratedPartialOutput(t *testing.T) { custom++ if custom == 1 { body := "data: {\"type\":\"response.output_text.delta\",\"delta\":\"Partial\"}\n\n" - return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + return &http.Response{Status: "200 OK", StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil } - return &http.Response{Status: "400 Bad Request", StatusCode: 400, Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil + return &http.Response{Status: "400 Bad Request", StatusCode: http.StatusBadRequest, Header: http.Header{}, Body: io.NopCloser(strings.NewReader("rejected"))}, nil })} _, _, _, err := a.CompactNow(t.Context()) if err == nil || custom != 2 || conversation != 0 { @@ -347,7 +348,7 @@ func TestCompactionFallbackRejectsSyntheticSSEHTTPStatus(t *testing.T) { a.CompactClient.HTTP = &http.Client{Transport: compactionTransport(func(*http.Request) (*http.Response, error) { custom++ body := "data: {\"type\":\"response.reasoning_summary_text.delta\",\"delta\":\"Thinking\"}\n\ndata: {\"type\":\"response.failed\",\"response\":{\"status\":\"failed\",\"error\":{\"code\":\"invalid_request\"}}}\n\n" - return &http.Response{Status: "200 OK", StatusCode: 200, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + return &http.Response{Status: "200 OK", StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil })} _, _, _, err := a.CompactNow(t.Context()) if err == nil || custom != 1 || conversation != 0 { diff --git a/internal/daemon/control.go b/internal/daemon/control.go index 27ef1598f..36a48cecf 100644 --- a/internal/daemon/control.go +++ b/internal/daemon/control.go @@ -210,7 +210,7 @@ func (c *Control) SessionMetadataCommand(ctx context.Context, admission session. if err := c.store.SetArchived(actorCtx, rootID, params.Archived); err != nil { return c.finishFailure(actorCtx, admission, err, &record) } - output, err = marshalClientOutput(protocol.ArchiveResult{Archived: params.Archived}, nil) + output, err = marshalClientOutput(protocol.ArchiveResult(params), nil) eventKind = "session.archived.updated" event.Archived = ¶ms.Archived case "session.rename": diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 6cf4ebc49..1ea3866ae 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -272,9 +272,6 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err cfg = config.Default() } meta.Effort = resolveEffort(cfg, meta.Model, meta.Provider, "", definition.Model.Effort) - if err := d.store.SetEffort(meta.ID, meta.Effort); err != nil { - return nil, err - } } authority, err := d.store.EnsureRootAuthority(d.ctx, meta.ID, rootGrants(definition, hasDefinition)) if err != nil { @@ -284,6 +281,13 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err if err != nil { return nil, err } + // Persist the resolved effort only after the factory succeeds, so a + // failed restore does not mutate the saved session. + if meta.Kind == session.SessionKindAgent && meta.Effort != "" { + if err := d.store.SetEffort(meta.ID, meta.Effort); err != nil { + return nil, err + } + } started := false var root *Session defer func() { diff --git a/internal/daemon/title_notifications_test.go b/internal/daemon/title_notifications_test.go index 95b3f8a2e..c39236ded 100644 --- a/internal/daemon/title_notifications_test.go +++ b/internal/daemon/title_notifications_test.go @@ -63,17 +63,20 @@ func titlePing(t *testing.T, transport messageTransport) { func connectTitleClient(t *testing.T, server *Server, id string, capabilities []string) messageTransport { t.Helper() // A short temporary directory keeps Unix socket paths below macOS's limit. - directory, err := os.MkdirTemp("", "whip-title-") + // t.TempDir() nests under the full test name and exceeds the 104-char socket cap. + directory, err := os.MkdirTemp("", "whip-title-") //nolint:usetesting // short path required for macOS socket limit if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = os.RemoveAll(directory) }) - listener, err := net.Listen("unix", filepath.Join(directory, "socket")) + var lc net.ListenConfig + listener, err := lc.Listen(context.Background(), "unix", filepath.Join(directory, "socket")) if err != nil { t.Fatal(err) } defer listener.Close() - clientSide, err := net.Dial("unix", listener.Addr().String()) + var dialer net.Dialer + clientSide, err := dialer.DialContext(context.Background(), "unix", listener.Addr().String()) if err != nil { t.Fatal(err) } @@ -388,10 +391,11 @@ func TestTitleNotificationsGeneratedResultRequiresCommittedWrite(t *testing.T) { } owner, root := openTitleLifecycle(t, store, rootID, &fakeRunner{}) changes := observeTitleChanges(t, owner) - if scenario == "write failure" { + switch scenario { + case "write failure": titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions BEGIN SELECT RAISE(ABORT,'title write failed'); END`) - } else if scenario == "event failure" { + case "event failure": titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON events WHEN NEW.kind='session.title.updated' BEGIN SELECT RAISE(ABORT,'title event failed'); END`) } @@ -500,10 +504,11 @@ func TestTitleNotificationsColdRenameCommitAndFailure(t *testing.T) { } t.Cleanup(func() { _ = owner.Close() }) changes := observeTitleChanges(t, owner) - if failure == "event" { + switch failure { + case "event": titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE INSERT ON events WHEN NEW.kind='session.title.updated' BEGIN SELECT RAISE(ABORT,'title event failed'); END`) - } else if failure == "write" { + case "write": titleFailureDB(t, path, `CREATE TRIGGER fail_title BEFORE UPDATE OF title ON sessions BEGIN SELECT RAISE(ABORT,'title write failed'); END`) } diff --git a/internal/session/title.go b/internal/session/title.go index 72dfffd95..432cd0b28 100644 --- a/internal/session/title.go +++ b/internal/session/title.go @@ -71,7 +71,7 @@ func authoredInputText(item InboxEnqueue) (string, error) { func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) (*TitleInitialization, error) { if item.RootID != item.AgentID || item.Origin != "client" || clientInputOrigin(item.Kind) == "" { - return nil, nil + return nil, nil //nolint:nilnil // nil signals no title initialization is needed } prompt, err := authoredInputText(item) if err != nil { @@ -79,7 +79,7 @@ func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) } title := provisionalTitleText(prompt) if title == "" { - return nil, nil + return nil, nil //nolint:nilnil // empty prompt yields no provisional title } var current, forkedFrom string var revision int64 @@ -88,7 +88,7 @@ func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) return nil, err } if current != "" || forkedFrom != "" || revision != 0 { - return nil, nil + return nil, nil //nolint:nilnil // already titled or forked } var firstTurn sql.NullString if err := tx.QueryRowContext(ctx, `SELECT @@ -97,7 +97,7 @@ func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) return nil, err } if firstTurn.Valid && firstTurn.String == "" { - return nil, nil + return nil, nil //nolint:nilnil // no first turn means no title to initialize } // Retained inbox metadata proves that previous human input had no usable // text. Unknown legacy previews are not evidence of an attachment-only start. @@ -121,7 +121,7 @@ func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) // 2048-byte boundary; the UTF-8 truncator can drop up to three bytes. if origin != "client" || preview == nil || strings.TrimSpace(preview.Text) != "" || preview.Truncated && len(preview.Text) >= 2048-utf8.UTFMax+1 { - return nil, nil + return nil, nil //nolint:nilnil // prior admission had text; not a first-turn candidate } if firstTurn.String == rootTurnID(item.AgentID, seq) { historyLinked = true @@ -136,7 +136,7 @@ func initializeInputTitleTx(ctx context.Context, tx *sql.Tx, item InboxEnqueue) // A history without a known no-text admission is historical, not a new // conversation. Reading only its first row also avoids expanded file text. if !historyLinked { - return nil, nil + return nil, nil //nolint:nilnil // history without a known no-text admission is not new } result, err := tx.ExecContext(ctx, `UPDATE sessions SET title=? WHERE id=? AND title=''`, title, item.RootID) if err != nil { diff --git a/internal/session/title_admission_test.go b/internal/session/title_admission_test.go index c80abb017..c22b0e3ed 100644 --- a/internal/session/title_admission_test.go +++ b/internal/session/title_admission_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "path/filepath" + "strconv" "strings" "sync" "testing" @@ -251,7 +252,7 @@ func TestConcurrentInputsInitializeOneTitle(t *testing.T) { var wg sync.WaitGroup for i := range callers { wg.Go(func() { - result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, fmt.Sprint(i), "submit", fmt.Sprintf("Prompt %d", i))) + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, strconv.Itoa(i), "submit", fmt.Sprintf("Prompt %d", i))) results <- result.TitleInitialization errs <- err }) @@ -281,7 +282,7 @@ func TestTitleWaitsForQueuedTextAndSurvivesTurnFailure(t *testing.T) { t.Run(status, func(t *testing.T) { store, root, agent := newSwarmFixture(t) for i, payload := range []string{"", "\t\n\u2003", strings.Repeat(" ", 3000)} { - result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, fmt.Sprint(i), "submit", payload)) + result, err := store.AdmitCommand(t.Context(), titleAdmission(root, agent, strconv.Itoa(i), "submit", payload)) if err != nil || result.TitleInitialization != nil { t.Fatalf("empty admission = %+v, %v", result, err) } diff --git a/internal/tui/client.go b/internal/tui/client.go index 84451edb4..ed513aa07 100644 --- a/internal/tui/client.go +++ b/internal/tui/client.go @@ -1926,9 +1926,7 @@ func (m *model) thinCommand(text string) (bubbletea.Model, bubbletea.Cmd) { if !ok { levels := m.effortsFor() names := make([]string, len(levels)) - for index := range levels { - names[index] = levels[index] - } + copy(names, levels) m.append(errStyle.Render("unknown effort level; " + m.modelName + " supports: " + strings.Join(names, ", "))) return m, nil } diff --git a/internal/tui/client_control_render_test.go b/internal/tui/client_control_render_test.go index 5f1cd7439..dfb256679 100644 --- a/internal/tui/client_control_render_test.go +++ b/internal/tui/client_control_render_test.go @@ -26,6 +26,7 @@ func TestRenderCompactionSettings(t *testing.T) { }, } { t.Run(test.name, func(t *testing.T) { + t.Parallel() output, err := json.Marshal(test.settings) if err != nil { t.Fatal(err) diff --git a/packages/sdk/src/session.ts b/packages/sdk/src/session.ts index cb0f3bb29..80abf8482 100644 --- a/packages/sdk/src/session.ts +++ b/packages/sdk/src/session.ts @@ -3,7 +3,7 @@ import type { CreateSessionParams, SessionCatalogParams, SubmitPayload, HistoryPageParams, MailboxPageParams, } from '@whip/protocol'; import type { WhipClient, CallOptions } from './client.js'; -import type { CommandOptions } from './command.js'; +import type { CommandHandle, CommandOptions } from './command.js'; import { Turn, permissionEvent, questionEvent, type PermissionEvent, type QuestionEvent, type RunOptions } from './turn.js'; import { encodeBase64, object } from './util.js'; @@ -12,7 +12,7 @@ export class Session { constructor(readonly client: WhipClient, readonly rootId: string) { if (!rootId) throw new TypeError('rootId is required'); } - command<O extends CommandOperation>(operation: O, payload: RuntimeOperations[O]['params'], options: Omit<CommandOptions, 'rootId'> = {}) { + command<O extends CommandOperation>(operation: O, payload: RuntimeOperations[O]['params'], options: Omit<CommandOptions, 'rootId'> = {}): CommandHandle<O> { return this.client.submit(operation, payload, { ...options, rootId: this.rootId }); } query<O extends QueryOperation>(operation: O, payload: RuntimeOperations[O]['params'], options: CallOptions = {}) { From 567bdebbae9aa21a7a09a7686a979824ea998a51 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Mon, 28 Sep 2026 18:18:12 -0700 Subject: [PATCH 16/67] fix(ci): generate protocol artifacts in docs job development gitignored packages/protocol/generated/ (previously committed on main) but the docs CI job was never updated to generate them. The sdk job got an "Initialize protocol artifacts and SDK" step but docs did not, so sdk-examples.test.ts failed with Cannot find module @whip/protocol. Add Go setup plus the same generate/build step to the docs job. --- .github/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6290f36c4..00de9cd41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -250,6 +250,10 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.sha }} + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: '24' @@ -257,6 +261,10 @@ jobs: - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK + run: | + npm run generate + npm run build - run: npm run check:docs - run: npm run test:docs - run: npm run test:docs:dev From 12f0ea0768b7d769765596c35c049fe80edfaeba Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 08:25:11 -0700 Subject: [PATCH 17/67] new folder in system dialog --- .ai-docs/plans/web-app/WORKFLOW-INVENTORY.md | 1 + apps/desktop/src/native.ts | 2 +- apps/desktop/tests/native.test.ts | 25 ++- docs/features.md | 1 + docs/frontend.md | 17 +- docs/protocol-v2.md | 8 + internal/daemon/host.go | 33 +++ internal/daemon/host_test.go | 130 ++++++++++++ internal/protocol/host.go | 11 + internal/protocol/registry.go | 1 + .../app/src/remote-directory-dialog.stylex.ts | 17 +- packages/app/src/remote-directory-dialog.tsx | 91 +++++++- packages/app/test/directory-picker.test.tsx | 2 +- .../app/test/remote-directory-dialog.test.tsx | 194 +++++++++++++++++- packages/sdk/src/services.ts | 9 +- packages/sdk/test/services.test.ts | 47 +++++ 16 files changed, 566 insertions(+), 23 deletions(-) diff --git a/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md b/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md index 2c71942ca..c6293e59a 100644 --- a/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md +++ b/.ai-docs/plans/web-app/WORKFLOW-INVENTORY.md @@ -36,6 +36,7 @@ The operation list is checked against the generated manifest by `packages/app/te | `rpc:history.page` | Web | Conversation pagination and inspector collections through the shared SDK view; bounded references remain explicit. | | `rpc:host.attention` | Web | Session sidebar/search and paged host attention; inactive roots are not opened. | | `rpc:host.directories.list` | Web | Welcome host directory picker and composer host completions. | +| `rpc:host.directory.create` | Web | New folder creates one child in the current directory on the selected execution host, without starting a session; Choose folder remains explicit. | | `rpc:host.directory.pick` | Web | Welcome native OS folder picker; falls back to the web directory browser where the host has no desktop picker. | | `rpc:host.skills.complete` | Web | Read-only New Chat slash skill suggestions for the selected host and agent definition before a session exists: negotiated global-only discovery without a folder, or the selected project's initial scope plus globals. | | `rpc:host.themes.list` | Web | Appearance settings: shared builtin/custom host themes and bounded JSON import. | diff --git a/apps/desktop/src/native.ts b/apps/desktop/src/native.ts index 8d0b6e663..17e841483 100644 --- a/apps/desktop/src/native.ts +++ b/apps/desktop/src/native.ts @@ -32,7 +32,7 @@ export class NativeEffects { async copy(value: unknown) { text(value, 8 << 20); clipboard.writeText(value); } async openExternal(value: unknown) { await shell.openExternal(externalURL(value)); } async pickDirectory() { - const result = await dialog.showOpenDialog(this.window, { properties: ['openDirectory'], title: 'Choose a local project directory' }); + const result = await dialog.showOpenDialog(this.window, { properties: ['openDirectory', 'createDirectory'], title: 'Choose a local project directory' }); return result.canceled ? undefined : result.filePaths[0]; } async beginSave(filename: unknown, mediaType: unknown, size: unknown) { diff --git a/apps/desktop/tests/native.test.ts b/apps/desktop/tests/native.test.ts index af3769238..41a2ebddc 100644 --- a/apps/desktop/tests/native.test.ts +++ b/apps/desktop/tests/native.test.ts @@ -4,7 +4,7 @@ import * as fs from 'node:fs/promises'; import Module from 'node:module'; import path from 'node:path'; import test, { type TestContext } from 'node:test'; -import type { BrowserWindow } from 'electron'; +import type { BrowserWindow, OpenDialogOptions } from 'electron'; import type { DesktopEvent } from '@whip/app/desktop-bridge'; function deferred<T = void>() { @@ -16,6 +16,8 @@ function gate() { return { entered: deferred(), resume: deferred() }; } const hooks: { open?: ReturnType<typeof gate>; write?: ReturnType<typeof gate>; sync?: ReturnType<typeof gate> } = {}; const opened: fs.FileHandle[] = []; let saveResult: Promise<{ canceled: boolean; filePath?: string }>; +let openResult = { canceled: false, filePaths: [] as string[] }; +let openOptions: OpenDialogOptions | undefined; let destroyed = false; let focused = false; let showCount = 0; @@ -32,7 +34,13 @@ class StubNotification extends EventEmitter { close() { this.closed = true; } } const electron = { - dialog: { showSaveDialog: async () => saveResult }, + dialog: { + showSaveDialog: async () => saveResult, + showOpenDialog: async (_window: BrowserWindow, options: OpenDialogOptions) => { + openOptions = options; + return openResult; + }, + }, clipboard: { writeText() {} }, shell: { openExternal: async () => {} }, Notification: StubNotification, @@ -186,6 +194,19 @@ test('native notification throttling is per session and bounds ownership without assert.equal(notices.filter(notice => !notice.closed).length, 0); }); +test('native directory picker enables creation and preserves selection and cancellation', async t => { + const f = await fixture(t); + openResult = { canceled: false, filePaths: [path.join(f.directory, 'chosen folder')] }; + assert.equal(await f.native.pickDirectory(), openResult.filePaths[0]); + assert.deepEqual(openOptions, { + properties: ['openDirectory', 'createDirectory'], title: 'Choose a local project directory', + }); + openResult = { canceled: true, filePaths: [path.join(f.directory, 'ignored')] }; + assert.equal(await f.native.pickDirectory(), undefined); + openResult = { canceled: false, filePaths: [] }; + assert.equal(await f.native.pickDirectory(), undefined); +}); + test('native effects reject privileged external schemes and malformed notification routes', async () => { const { externalURL, navigationPath } = await modules; for (const value of ['file:///etc/passwd', 'javascript:alert(1)', 'data:text/html,x', 'https://user:secret@example.test/', 'whip-app://app/']) diff --git a/docs/features.md b/docs/features.md index 2e5e5689f..fca524391 100644 --- a/docs/features.md +++ b/docs/features.md @@ -814,6 +814,7 @@ behavior to its owning code and repeatable validation. | Live session trace view (resizable execution tree, waterfall, and span details; pointer/keyboard dividers; ~30 fps live clock, paused when hidden/idle or motion is reduced) fed by durable nanosecond spans and live span events; one trace per root turn with child turns parented under their cause; OTLP/JSON export with GenAI + OpenInference attributes via `trace.export` and `whipcode sessions export` | `internal/session/{span,otlp_export}.go`, `internal/daemon/spans.go`, `packages/sdk/src/trace.ts`, `packages/app/src/{trace-view,trace-math}.ts*`, `cmd/whip/sessions_export.go` | `internal/session/{span,otlp_export}_test.go`, `internal/daemon/v2_event_schema_test.go`, `packages/sdk/test/trace.test.ts`, `packages/app/test/{trace-view,trace-math}.test.ts*` | | Attach to existing hosts, discover each directory tree, and route to retained sessions | `apps/web/src/main.tsx`, `packages/app/src/runtime.ts`, `packages/app/src/{shell,directory-picker}.tsx`, `internal/daemon/host.go` | `packages/app/test/runtime.test.ts`, `internal/daemon/host_test.go`, `apps/web/scripts/browser.mjs` | | Choose a Local working directory in the OS-native folder dialog (osascript/zenity/kdialog/PowerShell), falling back to the web directory browser; Remote uses its daemon directory browser | `host.directory.pick` in `internal/{protocol,daemon}/host.go`, `packages/sdk/src/services.ts`, `packages/app/src/directory-picker.tsx` | `TestDirectoryPickCommand`/`TestHostDirectoryPickValidation` in `internal/daemon/host_test.go` | +| Create a folder while choosing a new-session directory: native desktop New Folder, or inline New folder on the selected host; validate one child name, preserve errors, open the created folder, then explicitly Choose folder. Older hosts retain browsing with an update explanation. | `apps/desktop/src/native.ts`, `host.directory.create` in `internal/{protocol,daemon}/host.go`, `packages/sdk/src/services.ts`, `packages/app/src/remote-directory-dialog.tsx` | `apps/desktop/tests/native.test.ts`, `internal/daemon/host_test.go`, `packages/sdk/test/services.test.ts`, `packages/app/test/remote-directory-dialog.test.tsx` | | Multiple daemon connections, Local-owned saved profiles, verified identities, isolated disconnects and guided Local/Remote session creation | `packages/app/src/{hosts,runtime}.ts`, `{host-dialog,welcome,settings}.tsx`, `internal/config/remote_hosts.go`, daemon configuration service | `packages/app/test/hosts.test.ts`, `runtime.test.ts`, `sidebar-creation.test.tsx`; `internal/config/remote_hosts_test.go`; `TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts` | | Search and advisory attention across hosts, source labels/filter, independent bounded pagination and partial failures without root hydration | `packages/app/src/{session-search-dialog,attention}.tsx` | `packages/app/test/multi-host-discovery.test.tsx` | | Author data-only agent definitions in Settings (persona, rules, discovery, modules, capabilities, surface), copy built-ins, add revisions to registered ids, and pick the agent a new session runs | `packages/app/src/settings/agents.tsx`, `packages/app/src/definitions.ts`, `packages/app/src/welcome.tsx`, `session-tabs.ts` (`definition`) | `packages/app/test/settings-agents.test.tsx`, `sidebar-creation.test.tsx` (agent picker), `session-tabs.test.ts` | diff --git a/docs/frontend.md b/docs/frontend.md index 1a7838d49..ddcaa6c88 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -1450,7 +1450,8 @@ the shared Whip controls and theme tokens. Attachment and context controls remai disabled until a session exists; their backend operations require a root identity. The folder button opens the native system picker directly for the local machine and the host directory browser for remote hosts. If a local host has no native -picker available, the existing host-browser fallback remains available. +picker available, the existing host-browser fallback remains available. The desktop +native chooser enables folder creation through Electron’s `createDirectory` option. `remote-directory-dialog.tsx` implements the remote picker from Paper FYQ-1, G8C-1 and GHR-1 using shared Dialog, Input, Checkbox, Menu and Button components. @@ -1462,6 +1463,20 @@ Arrow keys move selection, Cmd/Ctrl+Shift+G edits the path and Cmd/Ctrl+Enter confirms. Escape first leaves path editing, then closes the dialog. Confirmation updates only the draft folder; it never sends the first message. +**New folder** creates one child of the currently displayed directory on the +selected execution host. Its inline name form keeps filesystem errors visible +without discarding the name. The SDK's `host.createDirectory` calls the host-scoped +`host.directory.create` mutating RPC, not a session command or an agent tool. +The daemon validates the absolute parent and single-component name and uses a +non-recursive filesystem mkdir; it never overwrites or silently adopts an existing +entry. Requests are not automatically retried. The advertised operation catalog +gates the action for older hosts, with an update-host explanation and a hover/focus +tooltip on **New folder**: “Host does not support folder creation. Please upgrade.” +After success, the picker invalidates cached directory listings on the captured +host, clears filtering/pagination and opens the created folder. **Choose folder** +remains an explicit separate confirmation. Closing or changing the host does not +undo creation; stale completions cannot navigate or choose on a different host. + Listings use `client.host.directories` with a 64-entry page, a debounced filename prefix and hidden folders off by default. Next/First controls expose pagination; counts describe the displayed page and host truncation remains visible. Navigation diff --git a/docs/protocol-v2.md b/docs/protocol-v2.md index ba55fa79b..636e51267 100644 --- a/docs/protocol-v2.md +++ b/docs/protocol-v2.md @@ -641,6 +641,14 @@ scan ceiling is reached. It reads no file bodies. Symlinks to directories are navigable. Filesystem changes can alter later pages; refresh the directory to obtain a new listing. +`host.directory.create` is a host-scoped mutating RPC available before a session +exists. It takes an existing absolute `parent` and one child `name`, creates a +single directory with the host process’s filesystem permissions, and returns its +absolute `path`. It rejects nested/invalid names and existing entries rather than +overwriting or adopting them. No parent directories are created and no session +is started. Clients must not automatically retry a lost creation response; inspect +the parent listing instead. Availability is advertised in the operation catalog. + `host.attention` reads a lightweight live index without opening every root or spending root subscriptions. `limit` is 1–128 and `max_bytes` is 4–512 KiB. Items contain root identity/title, decimal-string active-agent and pending-permission diff --git a/internal/daemon/host.go b/internal/daemon/host.go index 46a21588d..c745987f9 100644 --- a/internal/daemon/host.go +++ b/internal/daemon/host.go @@ -37,6 +37,12 @@ func (s *Server) handleHost(ctx context.Context, request rpcMessage) (any, *RPCE return nil, rpcFailure(-32602, err.Error()), true } result, err = hostDirectories(ctx, p) + case "host.directory.create": + var p protocol.HostDirectoryCreateParams + if err := decodeProviderParams(request.Params, &p); err != nil { + return nil, rpcFailure(-32602, "invalid directory creation parameters"), true + } + result, err = hostDirectoryCreate(ctx, p) case "host.directory.pick": var p protocol.HostDirectoryPickParams if err := decodeProviderParams(request.Params, &p); err != nil { @@ -175,6 +181,33 @@ func hostDirectories(ctx context.Context, p protocol.HostDirectoryParams) (proto return result, nil } +func hostDirectoryCreate(ctx context.Context, p protocol.HostDirectoryCreateParams) (protocol.HostDirectoryCreateResult, error) { + result := protocol.HostDirectoryCreateResult{} + if len(p.Parent) > 4096 || strings.ContainsRune(p.Parent, 0) || !filepath.IsAbs(p.Parent) { + return result, rpcFailure(-32602, "parent must be an absolute directory path of at most 4096 bytes") + } + if strings.TrimSpace(p.Name) == "" || len(p.Name) > 255 || p.Name == "." || p.Name == ".." || + strings.ContainsAny(p.Name, "/\\\x00") || !filepath.IsLocal(p.Name) { + return result, rpcFailure(-32602, "folder name must be one nonblank component of at most 255 bytes, without separators, NUL, dot or dot-dot") + } + // Windows otherwise normalizes trailing dots/spaces and accepts alternate streams. + if runtime.GOOS == "windows" && (strings.ContainsAny(p.Name, `<>:"|?*`) || + strings.HasSuffix(p.Name, ".") || strings.HasSuffix(p.Name, " ") || + strings.ContainsFunc(p.Name, func(r rune) bool { return r < 32 })) { + return result, rpcFailure(-32602, "folder name contains characters or aliases that are invalid on Windows") + } + if err := ctx.Err(); err != nil { + return result, err + } + path := filepath.Join(p.Parent, p.Name) + // The trusted host picker intentionally creates only one user-requested directory. + if err := os.Mkdir(path, 0o700); err != nil { + return result, fmt.Errorf("create folder: %w", err) + } + result.Path = path + return result, nil +} + // directoryPickCommand returns the native folder-chooser invocation for goos // (osascript on darwin, zenity or kdialog on linux, PowerShell Forms on // windows) and a predicate mapping a failure to a user cancellation. diff --git a/internal/daemon/host_test.go b/internal/daemon/host_test.go index 60b0c963b..94409afb6 100644 --- a/internal/daemon/host_test.go +++ b/internal/daemon/host_test.go @@ -315,6 +315,136 @@ func TestHostReadsDoNotOpenRootsAndQuestionsDisappear(t *testing.T) { } } +func TestHostDirectoryCreateRPC(t *testing.T) { + parent := t.TempDir() + // A server without a daemon or session proves host creation needs neither. + server := &Server{} + listParams, err := json.Marshal(protocol.HostDirectoryParams{Path: parent, Limit: 64, ShowHidden: true}) + if err != nil { + t.Fatal(err) + } + for _, name := range []string{"project", ".hidden", " spaced name", "café", strings.Repeat("a", 255)} { + params, err := json.Marshal(protocol.HostDirectoryCreateParams{Parent: parent, Name: name}) + if err != nil { + t.Fatal(err) + } + value, rpcErr, handled := server.handleHost(t.Context(), rpcMessage{Method: "host.directory.create", Params: params}) + result, ok := value.(protocol.HostDirectoryCreateResult) + if !handled || !ok || rpcErr != nil || result.Path != filepath.Join(parent, name) { + t.Fatalf("create %q: %+v %v handled=%v", name, value, rpcErr, handled) + } + info, err := os.Stat(result.Path) + if err != nil || !info.IsDir() { + t.Fatalf("created folder: %v %v", info, err) + } + value, rpcErr, handled = server.handleHost(t.Context(), rpcMessage{Method: "host.directories.list", Params: listParams}) + listing, ok := value.(protocol.HostDirectoryResult) + if !handled || !ok || rpcErr != nil || !slices.ContainsFunc(listing.Entries, func(entry protocol.HostDirectoryEntry) bool { + return entry.Name == name && entry.Path == result.Path + }) { + t.Fatalf("list created folder %q: %+v %v", name, value, rpcErr) + } + if _, err := hostDirectories(t.Context(), protocol.HostDirectoryParams{Path: result.Path, Limit: 1}); err != nil { + t.Fatalf("browse created folder: %v", err) + } + } +} + +func TestHostDirectoryCreateInvalidParams(t *testing.T) { + parent := t.TempDir() + for _, raw := range []string{"", "null", "[]", "{", "{}", `{"parent":1,"name":"x"}`, `{"parent":"/tmp","name":false}`, + `{"parent":"/tmp","name":"x","extra":true}`, `{"parent":"/tmp","name":"x"} {}`} { + _, rpcErr, handled := (&Server{}).handleHost(t.Context(), rpcMessage{Method: "host.directory.create", Params: json.RawMessage(raw)}) + if !handled || rpcErr == nil || rpcErr.Code != -32602 { + t.Fatalf("malformed params %q: %v handled=%v", raw, rpcErr, handled) + } + } + for _, name := range []string{"", " ", "\t\n", "\u2003", ".", "..", "../escape", "nested/child", "/absolute", `nested\child`, "bad\x00name", strings.Repeat("a", 256), strings.Repeat("é", 128)} { + _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: parent, Name: name}) + var rpcErr *RPCError + if !errors.As(err, &rpcErr) || rpcErr.Code != -32602 { + t.Fatalf("invalid name %q: %v", name, err) + } + } + for _, invalidParent := range []string{"", ".", "relative", "~/folder", parent + "\x00", "/" + strings.Repeat("a", 4096)} { + _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: invalidParent, Name: "child"}) + var rpcErr *RPCError + if !errors.As(err, &rpcErr) || rpcErr.Code != -32602 { + t.Fatalf("invalid parent %q: %v", invalidParent, err) + } + } + entries, err := os.ReadDir(parent) + if err != nil || len(entries) != 0 { + t.Fatalf("invalid requests changed parent: %v %v", entries, err) + } +} + +func TestHostDirectoryCreateFilesystemErrors(t *testing.T) { + parent := t.TempDir() + file := filepath.Join(parent, "file") + if err := os.WriteFile(file, []byte("preserve me"), 0o600); err != nil { + t.Fatal(err) + } + if err := os.Mkdir(filepath.Join(parent, "directory"), 0o700); err != nil { + t.Fatal(err) + } + for _, name := range []string{"file", "directory"} { + result, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: parent, Name: name}) + if !errors.Is(err, os.ErrExist) || result.Path != "" { + t.Fatalf("conflict %q: %+v %v", name, result, err) + } + } + if content, err := os.ReadFile(file); err != nil || string(content) != "preserve me" { + t.Fatalf("existing file changed: %q %v", content, err) + } + missing := filepath.Join(parent, "missing") + if _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: missing, Name: "child"}); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("missing parent: %v", err) + } + if _, err := os.Stat(missing); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("created missing parent recursively: %v", err) + } + if _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: file, Name: "child"}); err == nil { + t.Fatal("accepted file as parent") + } + ctx, cancel := context.WithCancel(t.Context()) + cancel() + if _, err := hostDirectoryCreate(ctx, protocol.HostDirectoryCreateParams{Parent: parent, Name: "cancelled"}); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled create: %v", err) + } + if _, err := os.Stat(filepath.Join(parent, "cancelled")); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("cancelled request created folder: %v", err) + } +} + +func TestHostDirectoryCreateUnwritableParent(t *testing.T) { + if runtime.GOOS == "windows" || os.Geteuid() == 0 { + t.Skip("requires POSIX permissions and an unprivileged process") + } + parent := t.TempDir() + if err := os.Chmod(parent, 0o500); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = os.Chmod(parent, 0o700) }) + if _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: parent, Name: "child"}); !errors.Is(err, os.ErrPermission) { + t.Fatalf("unwritable parent: %v", err) + } +} + +func TestHostDirectoryCreateWindowsNames(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("Windows naming rules") + } + parent := t.TempDir() + for _, name := range []string{"CON", "NUL", "COM1", "LPT1", "CONOUT$", "COM¹", "trailing.", "trailing ", ".. ", "stream:ads", "wild*card", "what?", "a<b", "a>b", `a"b`, "a|b", "control\x01"} { + _, err := hostDirectoryCreate(t.Context(), protocol.HostDirectoryCreateParams{Parent: parent, Name: name}) + var rpcErr *RPCError + if !errors.As(err, &rpcErr) || rpcErr.Code != -32602 { + t.Fatalf("invalid Windows name %q: %v", name, err) + } + } +} + func TestHostDirectoryBoundsAndFilters(t *testing.T) { directory := t.TempDir() for _, name := range []string{"alpha", "beta", ".hidden"} { diff --git a/internal/protocol/host.go b/internal/protocol/host.go index 7acf38070..3000ab2e4 100644 --- a/internal/protocol/host.go +++ b/internal/protocol/host.go @@ -46,6 +46,17 @@ type HostDirectoryPickParams struct { Start string `json:"start,omitempty"` } +// HostDirectoryCreateParams creates one directory in an existing absolute parent. +// Name is a single component; existing files and directories are never adopted. +type HostDirectoryCreateParams struct { + Parent string `json:"parent"` + Name string `json:"name"` +} + +type HostDirectoryCreateResult struct { + Path string `json:"path"` +} + type HostDirectoryPickResult struct { Path string `json:"path,omitempty"` Cancelled bool `json:"cancelled"` diff --git a/internal/protocol/registry.go b/internal/protocol/registry.go index 7fa7d30ff..000543ff4 100644 --- a/internal/protocol/registry.go +++ b/internal/protocol/registry.go @@ -106,6 +106,7 @@ var rpcOperations = []Operation{ rpc[HostSkillCompletionParams, CompletionResult]("host.skills.complete", Query, "host-runtime", false), rpc[HostDirectoryParams, HostDirectoryResult]("host.directories.list", Query, "host-runtime", false), rpc[HostDirectoryPickParams, HostDirectoryPickResult]("host.directory.pick", Query, "host-runtime", false), + rpc[HostDirectoryCreateParams, HostDirectoryCreateResult]("host.directory.create", Ephemeral, "host-runtime", false), rpc[HostAttentionParams, HostAttentionResult]("host.attention", Query, "host-runtime", false), rpc[EmptyParams, theme.CatalogResult]("host.themes.list", Query, "host-runtime", false), rpc[HostThemeResolveParams, theme.Resolved]("host.themes.resolve", Query, "host-runtime", false), diff --git a/packages/app/src/remote-directory-dialog.stylex.ts b/packages/app/src/remote-directory-dialog.stylex.ts index d66626772..ae8c0bc47 100644 --- a/packages/app/src/remote-directory-dialog.stylex.ts +++ b/packages/app/src/remote-directory-dialog.stylex.ts @@ -5,20 +5,29 @@ export const styles = stylex.create({ dialog: { width: 'min(840px, calc(100vw - 24px))', height: { default: 592, [scale.phone]: 'min(720px, calc(100dvh - 24px))' }, maxHeight: 'calc(100dvh - 24px)', padding: 0, gap: 0, overflow: 'hidden' }, header: { paddingBlock: 16, paddingInline: 24, alignItems: 'center', height: 76, flexShrink: 0, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, body: { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, gap: 0 }, - workspace: { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, overflowY: { default: 'hidden', '@media (max-height: 600px)': 'auto' } }, + workspace: { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, overflowY: { default: 'hidden', [scale.phone]: 'auto', '@media (max-height: 600px)': 'auto' } }, host: { display: 'flex', alignItems: 'center', gap: 8, fontSize: typography.size12, lineHeight: '18px', minWidth: 0, whiteSpace: 'nowrap' }, hostName: { minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }, connectionStatus: { display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }, hostDetail: { display: { default: 'block', [scale.phone]: 'none' }, minWidth: 0, maxWidth: 260, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }, dot: { width: 5, height: 5, flexShrink: 0, borderRadius: '50%', backgroundColor: surface.secondaryText }, connected: { backgroundColor: colors.success }, - navigation: { display: 'flex', alignItems: 'center', gap: 8, paddingBlock: 8, paddingInline: 16, minHeight: 52, flexShrink: 0, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, - breadcrumbs: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0, overflowX: 'auto', whiteSpace: 'nowrap' }, + navigation: { display: 'flex', flexWrap: { default: 'nowrap', [scale.phone]: 'wrap' }, alignItems: 'center', gap: 8, paddingBlock: 8, paddingInline: 16, minHeight: 52, flexShrink: 0, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, + breadcrumbs: { display: 'flex', alignItems: 'center', flex: { default: '1 1 0', [scale.phone]: '1 1 calc(100% - 104px)' }, minWidth: 0, overflowX: 'auto', whiteSpace: 'nowrap' }, crumb: { display: 'flex', alignItems: 'center', flexShrink: 0 }, crumbButton: { paddingInline: 8, maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis' }, pathForm: { display: 'flex', alignItems: 'center', gap: 8, width: '100%', flexWrap: { default: 'nowrap', [scale.phone]: 'wrap' } }, pathInput: { fontFamily: typography.mono, fontSize: typography.size12, flex: { default: '1 1 0', [scale.phone]: '1 1 100%' } }, - browser: { display: 'flex', flex: { default: '1 1 0', '@media (max-height: 600px)': '0 0 320px' }, minHeight: 0 }, + createTrigger: { display: 'inline-flex' }, + unsupportedCreate: { pointerEvents: 'none' }, + createNotice: { margin: 0, paddingBlock: 8, paddingInline: 16, flexShrink: 0, fontSize: typography.size12, lineHeight: '18px', color: surface.secondaryText, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, + createForm: { display: 'flex', flexDirection: 'column', flexShrink: 0, gap: 8, paddingBlock: 12, paddingInline: 16, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, + createDestination: { display: 'flex', flexDirection: 'column', gap: 2, minWidth: 0, overflowWrap: 'anywhere' }, + createPath: { fontFamily: typography.mono, fontSize: typography.size12, lineHeight: '18px', overflowWrap: 'anywhere', maxHeight: 36, overflowY: 'auto' }, + createControls: { display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 8 }, + createLabel: { flex: { default: '0 0 auto', [scale.phone]: '1 1 100%' } }, + createInput: { flex: '1 1 100px', minWidth: 0 }, + browser: { display: 'flex', flex: { default: '1 1 0', '@media (max-height: 600px)': '0 0 320px' }, minHeight: { default: 0, [scale.phone]: 280 } }, mobileLocations: { display: { default: 'none', [scale.phone]: 'flex' }, flexShrink: 0, paddingInline: 12, borderBottomWidth: 1, borderBottomStyle: 'solid', borderBottomColor: colors.border }, locations: { display: { default: 'flex', [scale.phone]: 'none' }, flexDirection: 'column', width: 168, flexShrink: 0, padding: 12, paddingTop: 16, borderRightWidth: 1, borderRightStyle: 'solid', borderRightColor: colors.border, backgroundColor: surface.navigation, overflowY: 'auto' }, locationLabel: { margin: 0, paddingInline: 10, paddingBottom: 8, fontSize: typography.size12, color: surface.secondaryText }, diff --git a/packages/app/src/remote-directory-dialog.tsx b/packages/app/src/remote-directory-dialog.tsx index 8d22552f2..348406241 100644 --- a/packages/app/src/remote-directory-dialog.tsx +++ b/packages/app/src/remote-directory-dialog.tsx @@ -1,10 +1,10 @@ -import { useCallback, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore, type KeyboardEvent } from 'react'; +import { useCallback, useEffect, useId, useLayoutEffect, useRef, useState, useSyncExternalStore, type KeyboardEvent } from 'react'; import { keepPreviousData, useQuery, useQueryClient } from '@tanstack/react-query'; import { useWhipConnection } from '@whip/sdk/react'; import type { WhipClient } from '@whip/sdk'; import type { SessionListView } from '@whip/sdk/state'; -import { Button, Checkbox, Dialog, IconButton, Input, Menu, Spinner } from '@whip/ui'; -import { ArrowLeft, ArrowUp, Check, ChevronDown, ChevronRight, Folder, HardDrive, Home, Pencil, Search, Server } from 'lucide-react'; +import { Button, Checkbox, Dialog, IconButton, Input, Menu, Spinner, Tooltip } from '@whip/ui'; +import { ArrowLeft, ArrowUp, Check, ChevronDown, ChevronRight, Folder, FolderPlus, HardDrive, Home, Pencil, Search, Server } from 'lucide-react'; import * as stylex from '@stylexjs/stylex'; import { errorMessage } from './platform'; import { layout } from './styles'; @@ -62,6 +62,22 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, const [actionError, setActionError] = useState(''); const [confirming, setConfirming] = useState(false); const [reconnecting, setReconnecting] = useState(false); + const [createParent, setCreateParent] = useState(''); + const [newName, setNewName] = useState(''); + const [createError, setCreateError] = useState(''); + const [createdPath, setCreatedPath] = useState(''); + const [creating, setCreating] = useState(false); + const createVersion = useRef(0); + const pendingCreate = useRef<symbol | null>(null); + const createInput = useRef<HTMLInputElement>(null); + const newFolderButton = useRef<HTMLButtonElement>(null); + const restoreCreateFocus = useRef(false); + const createId = useId(); + const supportsCreate = client.supports('rpc', 'host.directory.create'); + const nameError = !newName.trim() ? 'Enter a folder name.' + : newName === '.' || newName === '..' || /[\\/\0]/.test(newName) || /^[a-z]:/i.test(newName) + ? 'Enter one folder name, not a path.' + : new TextEncoder().encode(newName).length > 255 ? 'Use a folder name of at most 255 bytes.' : ''; const input = useRef<HTMLInputElement>(null); const editButton = useRef<HTMLButtonElement>(null); const rows = useRef<HTMLUListElement>(null); @@ -88,7 +104,8 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, const ready = online && !disabled && !editing && filterValid && filter === prefix && query.isSuccess && !query.isFetching && !query.isPlaceholderData; // A child's own listing validates readability and can also serve its next open. const selectedFolder = useQuery({ ...directoryOptions(client, { path: selected }), enabled: ready && !!selected }); - const canChoose = !confirming && ready && (!selected || (selectedFolder.isSuccess && !selectedFolder.isFetching)); + const canCreate = supportsCreate && ready && !confirming && !creating && !!directoryCrumbs(query.data?.path ?? '').length; + const canChoose = !createParent && !creating && !confirming && ready && (!selected || (selectedFolder.isSuccess && !selectedFolder.isFetching)); const chosen = selected ? selectedFolder.data?.path ?? selected : query.data?.path ?? path; const current = query.error ? path : query.data?.path ?? path; const crumbs = directoryCrumbs(current); @@ -138,10 +155,56 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, const first = rows.current?.querySelector<HTMLButtonElement>('[data-folder-select]'); (first ?? filterInput.current)?.focus(); }, [ready, current]); + function retireCreate() { + createVersion.current++; pendingCreate.current = null; + setCreateParent(''); setNewName(''); setCreateError(''); setCreatedPath(''); setCreating(false); + } + useLayoutEffect(() => { + retireCreate(); + return () => { createVersion.current++; }; + }, [client, connection.info?.runtime_id, online, disabled]); + useLayoutEffect(() => { + if (createParent && !creating) createInput.current?.focus(); + else if (restoreCreateFocus.current) { newFolderButton.current?.focus(); restoreCreateFocus.current = false; } + }, [createParent, creating]); + function cancelCreate() { restoreCreateFocus.current = true; retireCreate(); } + function close() { createVersion.current++; choiceVersion.current++; onClose(); } + function startCreate() { + if (!canCreate || pendingCreate.current) return; + resetSelection(); setCreatedPath(''); setNewName(''); setCreateError(''); setCreateParent(query.data!.path); + } + async function createFolder() { + if (!canCreate || !createParent || nameError || pendingCreate.current) return; + const parent = createParent, runtime = connection.info?.runtime_id; + const version = createVersion.current, request = Symbol(); + pendingCreate.current = request; setCreating(true); setCreateError(''); + cache.cancel(client); + const currentRequest = () => alive.current && version === createVersion.current + && pendingCreate.current === request && client.getSnapshot().state === 'connected' + && client.getSnapshot().info?.runtime_id === runtime; + let created: { path: string }; + try { + // A lost response must never automatically repeat a filesystem mutation. + created = await client.host.createDirectory({ parent, name: newName }); + } catch (error) { + if (currentRequest()) { setCreateError(errorMessage(error)); setCreating(false); pendingCreate.current = null; createInput.current?.focus(); } + return; + } + // Paths may be symlink aliases; invalidate this host's bounded directory cache + // rather than guessing filesystem identity. Do this even after the picker closes. + const hostListings = { queryKey: ['directories', runtime] }; + await queries.cancelQueries(hostListings); + void queries.invalidateQueries({ ...hostListings, refetchType: currentRequest() ? 'none' : 'active' }); + if (!currentRequest()) return; + filterInput.current?.focus(); focusAfterNavigation.current = true; + navigate(created.path); setHidden(false); setCreatedPath(created.path); + } function resetSelection() { choiceVersion.current++; setSelected(''); setActionError(''); } function selectFolder(target: string) { choiceVersion.current++; cache.cancel(client, { path: target }); setSelected(target); setActionError(''); } function navigate(target: string, back = false) { if (!online || disabled) return; + if (createParent) filterInput.current?.focus(); + retireCreate(); // Cached navigation can replace the focused row immediately. Move focus // before removal so the dialog's focus trap does not restore it afterward. if (rows.current?.contains(document.activeElement)) filterInput.current?.focus(); @@ -150,7 +213,7 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, cache.cancel(client, { path: target }); setPath(target); setTyped(target); setEditing(false); setFilter(''); setPrefix(''); setAfter(undefined); resetSelection(); } - function editPath() { choiceVersion.current++; setTyped(current || '~'); setEditing(true); setActionError(''); } + function editPath() { retireCreate(); choiceVersion.current++; setTyped(current || '~'); setEditing(true); setActionError(''); } function cancelEdit() { setEditing(false); setTyped(current); setActionError(''); } const choice = useRef(''); choice.current = online && !disabled && !editing && !query.isPlaceholderData && filter === prefix ? chosen : ''; @@ -178,6 +241,8 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, event.preventDefault(); event.stopPropagation(); editPath(); } else if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { event.preventDefault(); event.stopPropagation(); choose(); + } else if (event.key === 'Escape' && createParent && !creating) { + event.preventDefault(); event.stopPropagation(); cancelCreate(); } else if (event.key === 'Escape' && editing) { event.preventDefault(); event.stopPropagation(); cancelEdit(); } @@ -199,7 +264,8 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, { id: 'root', label: 'File system', icon: <HardDrive size={14} />, onSelect: () => navigate(crumbs[0]?.path ?? '/'), disabled: !online || disabled }, ...recent.map(folder => ({ id: folder, label: folderName(folder), icon: <Folder size={14} />, onSelect: () => navigate(folder), disabled: !online || disabled })), ]; - return <Dialog open onOpenChange={open => { if (!open) onClose(); }} title="Choose a folder" initialFocus={filterInput} + const newFolderControl = <Button ref={newFolderButton} variant="ghost" disabled={!canCreate || !!createParent} xstyle={!supportsCreate && styles.unsupportedCreate} aria-describedby={!supportsCreate ? createId + '-unsupported' : undefined} onClick={startCreate}><FolderPlus size={14} />New folder</Button>; + return <Dialog open onOpenChange={open => { if (!open) close(); }} title="Choose a folder" initialFocus={filterInput} xstyle={styles.dialog} headerXstyle={styles.header} bodyXstyle={styles.body} description={<span {...stylex.props(styles.host)}><Server size={14} /><span title={hostName} {...stylex.props(styles.hostName)}>{hostName}</span>{host?.detail && host.detail.replace(/^https?:\/\//, '').replace(/\/$/, '') !== hostName && <span title={host.detail} {...stylex.props(styles.hostDetail)}>{host.detail}</span>}<span {...stylex.props(styles.connectionStatus)}><span {...stylex.props(styles.dot, online && styles.connected)} />{online ? 'Connected' : 'Disconnected'}</span></span>}> <div onKeyDownCapture={shortcuts} {...stylex.props(styles.body)}> @@ -214,7 +280,16 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, <nav aria-label="Folder path" {...stylex.props(styles.breadcrumbs)}>{crumbs.length ? crumbs.map((crumb, index) => <span key={crumb.path} {...stylex.props(styles.crumb)}>{index > 0 && <ChevronRight size={12} />}<Button variant="ghost" title={crumb.path} aria-current={index === crumbs.length - 1 ? 'location' : undefined} disabled={!online || disabled} xstyle={styles.crumbButton} onPointerEnter={() => warm(crumb.path)} onFocus={() => warm(crumb.path)} onClick={() => navigate(crumb.path)}>{crumb.label}</Button></span>) : <span>{current || 'Home'}</span>}</nav> <Button ref={editButton} variant="ghost" onClick={editPath} disabled={!online || disabled}><Pencil size={14} /><span>Edit path</span></Button> </>} + {!editing && (supportsCreate ? newFolderControl : <Tooltip label="Host does not support folder creation. Please upgrade."><span tabIndex={0} {...stylex.props(styles.createTrigger)}>{newFolderControl}</span></Tooltip>)} </div> + {!supportsCreate && <p id={createId + '-unsupported'} {...stylex.props(styles.createNotice)}>Update this host to create folders here. You can still browse and choose a folder.</p>} + {createParent && <form aria-label="New folder" {...stylex.props(styles.createForm)} onSubmit={event => { event.preventDefault(); event.stopPropagation(); void createFolder(); }}> + <div id={createId + '-destination'} {...stylex.props(styles.createDestination)}><span {...stylex.props(styles.caption)}>Create in {hostName}</span><span {...stylex.props(styles.createPath)}>{createParent}</span></div> + <div {...stylex.props(styles.createControls)}><label htmlFor={createId} {...stylex.props(styles.caption, styles.createLabel)}>Folder name</label><Input id={createId} ref={createInput} value={newName} maxLength={256} disabled={!online || disabled || creating} autoComplete="off" aria-invalid={!!createError || (!!newName && !!nameError)} aria-describedby={createId + '-destination ' + createId + '-feedback'} xstyle={styles.createInput} onChange={event => { setNewName(event.target.value); setCreateError(''); }} /> + <div {...stylex.props(styles.actions)}><Button type="submit" size="sm" disabled={!canCreate || !!nameError} loading={creating}>Create</Button><Button size="sm" variant="ghost" disabled={creating} onClick={cancelCreate}>Cancel</Button></div> + </div> + <span id={createId + '-feedback'} role={createError ? 'alert' : 'status'} {...stylex.props(styles.caption, (!!createError || (!!newName && !!nameError)) && styles.selectionError)}>{createError || (creating ? 'Creating folder… Closing this dialog won’t undo creation.' : newName ? nameError : 'Enter one folder name, not a path.')}</span> + </form>} <div {...stylex.props(styles.mobileLocations)}><Menu align="start" trigger={<Button variant="ghost"><Home size={14} />Locations<ChevronDown size={14} /></Button>} items={locations} /></div> <div {...stylex.props(styles.browser)}> <aside aria-label="Locations" {...stylex.props(styles.locations)}><p {...stylex.props(styles.locationLabel)}>Locations</p> @@ -248,10 +323,10 @@ export function RemoteDirectoryDialog({ client, value, disabled, host, onClose, </div> </div> <footer {...stylex.props(styles.footer)}><div aria-live="polite" {...stylex.props(styles.selection)}><span {...stylex.props(styles.caption)}>{selected ? 'Selected folder' : 'Current folder'}</span><span title={chosen} {...stylex.props(styles.selectedPath)}>{chosen || 'Home'}</span> - <div {...stylex.props(styles.selectionStatus)}>{(actionError || (selected && selectedFolder.error)) + <div {...stylex.props(styles.selectionStatus)}>{createdPath && <span role="status" {...stylex.props(styles.caption)}>{query.error ? 'Folder created, but its contents could not be loaded. Retry the listing; do not create it again.' : 'Folder created. Choose folder to use it.'}</span>}{(actionError || (selected && selectedFolder.error)) ? <span role="alert" {...stylex.props(styles.selectionError)}>{actionError || `Can’t use this folder: ${errorMessage(selectedFolder.error)}`}</span> : online && (confirming || (selected && selectedFolder.isFetching)) ? <span {...stylex.props(styles.caption)}>Checking folder…</span> : null}</div> - </div><div {...stylex.props(styles.actions)}><Button variant="ghost" onClick={onClose}>Cancel</Button><Button variant="primary" disabled={!canChoose} onClick={choose}>Choose folder</Button></div></footer> + </div><div {...stylex.props(styles.actions)}><Button variant="ghost" onClick={close}>Cancel</Button><Button variant="primary" disabled={!canChoose} onClick={choose}>Choose folder</Button></div></footer> </div> </Dialog>; } diff --git a/packages/app/test/directory-picker.test.tsx b/packages/app/test/directory-picker.test.tsx index e5166d7ca..d3122a561 100644 --- a/packages/app/test/directory-picker.test.tsx +++ b/packages/app/test/directory-picker.test.tsx @@ -12,7 +12,7 @@ function fixture() { const pickDirectory = vi.fn(() => new Promise<{ path: string }>(resolve => { finish = resolve; })); const directories = vi.fn(async ({ path }: { path?: string }) => ({ path: path || '/start', entries: [], has_more: false })); const connection = { state: 'connected', info: { runtime_id: 'local' } }; - const client = { subscribe: () => () => {}, getSnapshot: () => connection, host: { pickDirectory, directories } } as unknown as WhipClient; + const client = { supports: () => false, subscribe: () => () => {}, getSnapshot: () => connection, host: { pickDirectory, directories } } as unknown as WhipClient; const onSelect = vi.fn(), submit = vi.fn(); const query = new QueryClient({ defaultOptions: { queries: { retry: false, gcTime: 0 } } }); const tree = (target = client, native = false, sessionTrigger = false) => <ThemeProvider initialTheme="light"><UIProvider><QueryClientProvider client={query}> diff --git a/packages/app/test/remote-directory-dialog.test.tsx b/packages/app/test/remote-directory-dialog.test.tsx index db627f6e9..964430c55 100644 --- a/packages/app/test/remote-directory-dialog.test.tsx +++ b/packages/app/test/remote-directory-dialog.test.tsx @@ -1,4 +1,5 @@ import { act, fireEvent, render, screen, waitFor, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { afterEach, beforeEach, expect, it, vi } from 'vitest'; import { ThemeProvider, UIProvider } from '@whip/ui'; @@ -10,17 +11,21 @@ beforeEach(() => vi.stubGlobal('matchMedia', () => ({ matches: false, addEventLi afterEach(() => vi.unstubAllGlobals()); const result = (path: string, names: string[] = []) => ({ path, parent: path.slice(0, path.lastIndexOf('/')) || '/', entries: names.map(name => ({ name, path: `${path}/${name}` })), has_more: false, next_after: '' }); function deferred<T>() { let resolve!: (value: T) => void; const promise = new Promise<T>(done => { resolve = done; }); return { promise, resolve }; } -function fixture() { +function fixture(supported = true) { let snapshot = { state: 'connected', info: { runtime_id: 'kuzco' } }; const listeners = new Set<() => void>(); const directories = vi.fn(async (params: { path?: string; limit?: number; prefix?: string; show_hidden?: boolean; after?: string }, _options?: { signal?: AbortSignal }) => result(params.path || '/home/sam', params.path === '/home/sam' ? ['alpha', 'beta', 'private'] : [])); - const client = { subscribe: (listener: () => void) => { listeners.add(listener); return () => listeners.delete(listener); }, getSnapshot: () => snapshot, host: { directories } } as unknown as WhipClient; + const createDirectory = vi.fn(async ({ parent, name }: { parent: string; name: string }) => ({ path: `${parent}/${name}` })); + const supports = vi.fn(() => supported); + const client = { supports, subscribe: (listener: () => void) => { listeners.add(listener); return () => listeners.delete(listener); }, getSnapshot: () => snapshot, host: { directories, createDirectory } } as unknown as WhipClient; const query = new QueryClient({ defaultOptions: { queries: { retry: false, staleTime: Infinity } } }); const onSelect = vi.fn(), onClose = vi.fn(); const reconnect = vi.fn(async () => { setState('connected'); }); function setState(state: string) { act(() => { snapshot = { ...snapshot, state }; listeners.forEach(listener => listener()); }); } - const view = render(<ThemeProvider initialTheme="dark"><UIProvider><QueryClientProvider client={query}><RemoteDirectoryDialog client={client} host={{ name: 'Kuzco', detail: 'sam@kuzco', reconnect }} value="/home/sam" disabled={false} onSelect={onSelect} onClose={onClose} /></QueryClientProvider></UIProvider></ThemeProvider>); - return { client, directories, query, onSelect, onClose, reconnect, setState, view }; + function setRuntime(runtime_id: string) { act(() => { snapshot = { ...snapshot, info: { runtime_id } }; listeners.forEach(listener => listener()); }); } + const dialog = (activeClient = client, disabled = false) => <ThemeProvider initialTheme="dark"><UIProvider><QueryClientProvider client={query}><RemoteDirectoryDialog client={activeClient} host={{ name: 'Kuzco', detail: 'sam@kuzco', reconnect }} value="/home/sam" disabled={disabled} onSelect={onSelect} onClose={onClose} /></QueryClientProvider></UIProvider></ThemeProvider>; + const view = render(dialog()); + return { client, directories, createDirectory, supports, query, onSelect, onClose, reconnect, setState, setRuntime, view, rerender: (activeClient = client, disabled = false) => view.rerender(dialog(activeClient, disabled)) }; } const choose = () => screen.getByRole('button', { name: 'Choose folder', exact: true }) as HTMLButtonElement; const ready = () => waitFor(() => expect(choose().disabled).toBe(false)); @@ -165,6 +170,187 @@ it('retains rows and breadcrumbs during a slow navigation and reuses Back withou await ready(); expect(folder('beta')).toBeTruthy(); expect(homeReads()).toBe(before); }); +const newFolder = () => screen.getByRole('button', { name: 'New folder', exact: true }) as HTMLButtonElement; +function nameFolder(name = 'project') { + fireEvent.click(newFolder()); + const input = screen.getByRole('textbox', { name: 'Folder name' }) as HTMLInputElement; + fireEvent.change(input, { target: { value: name } }); + return input; +} +const submitFolder = (input: HTMLElement) => fireEvent.submit(input.closest('form')!); + +it('creates in the displayed parent, opens the result, and still requires explicit choice', async () => { + const f = fixture(); await ready(); + fireEvent.click(folder('alpha')); await ready(); + const input = nameFolder(); + expect(document.activeElement).toBe(input); + expect(screen.getByRole('form', { name: 'New folder' }).textContent).toContain('Create in Kuzco/home/sam'); + expect(choose().disabled).toBe(true); + submitFolder(input); + await screen.findByText('Folder created. Choose folder to use it.'); await ready(); + expect(f.createDirectory).toHaveBeenCalledExactlyOnceWith({ parent: '/home/sam', name: 'project' }); + expect(screen.getByRole('navigation', { name: 'Folder path' }).textContent).toContain('project'); + expect(f.onSelect).not.toHaveBeenCalled(); + fireEvent.click(choose()); + await waitFor(() => expect(f.onSelect).toHaveBeenCalledExactlyOnceWith('/home/sam/project')); +}); + +it('guards duplicate submissions and retains a conflict inline for correction without retries', async () => { + const f = fixture(); await ready(); + let reject!: (error: Error) => void; + f.createDirectory.mockImplementationOnce(() => new Promise((_resolve, fail) => { reject = fail; })); + const input = nameFolder('alpha'); + submitFolder(input); submitFolder(input); + expect(f.createDirectory).toHaveBeenCalledTimes(1); + expect(input.disabled).toBe(true); + expect(newFolder().disabled).toBe(true); + expect(within(screen.getByRole('form', { name: 'New folder' })).getByRole('button', { name: 'Cancel' }).hasAttribute('disabled')).toBe(true); + await act(async () => reject(new Error('A folder already exists'))); + await screen.findByRole('alert'); + expect(screen.getByRole('alert').textContent).toBe('A folder already exists'); + expect(input.value).toBe('alpha'); expect(document.activeElement).toBe(input); + expect(f.createDirectory).toHaveBeenCalledTimes(1); + fireEvent.change(input, { target: { value: 'corrected' } }); submitFolder(input); + await ready(); expect(f.createDirectory).toHaveBeenCalledTimes(2); + expect(f.onSelect).not.toHaveBeenCalled(); +}); + +it.each(['', ' ', '.', '..', 'nested/name', 'nested\\name', '/absolute', 'C:drive', 'nul\0name', 'é'.repeat(128)])('rejects invalid folder name %j without a mutation', async name => { + const f = fixture(); await ready(); + const input = nameFolder(name); + expect(within(screen.getByRole('form', { name: 'New folder' })).getByRole('button', { name: 'Create' }).hasAttribute('disabled')).toBe(true); + submitFolder(input); expect(f.createDirectory).not.toHaveBeenCalled(); +}); + +it('cancels the form with Escape or Cancel and restores focus without mutating', async () => { + const f = fixture(); await ready(); + const input = nameFolder(); + fireEvent.keyDown(input, { key: 'Escape' }); + expect(screen.queryByRole('form', { name: 'New folder' })).toBeNull(); + expect(document.activeElement).toBe(newFolder()); expect(f.onClose).not.toHaveBeenCalled(); + nameFolder(); + fireEvent.click(within(screen.getByRole('form', { name: 'New folder' })).getByRole('button', { name: 'Cancel' })); + expect(document.activeElement).toBe(newFolder()); + expect(f.createDirectory).not.toHaveBeenCalled(); expect(choose().disabled).toBe(false); +}); + +it.each(['hover', 'focus'])('keeps older hosts browseable with an upgrade tooltip on %s and no creation', async interaction => { + const f = fixture(false); await ready(); + expect(f.supports).toHaveBeenCalledWith('rpc', 'host.directory.create'); + expect(newFolder().disabled).toBe(true); + expect(screen.getByText(/Update this host to create folders/)).toBeTruthy(); + expect(screen.queryByText('Host does not support folder creation. Please upgrade.')).toBeNull(); + await waitFor(() => expect(document.activeElement).toBe(screen.getByRole('textbox', { name: 'Filter folders by prefix' }))); + const trigger = newFolder().parentElement!; + if (interaction === 'hover') await userEvent.setup().hover(trigger); + else act(() => trigger.focus()); + expect(await screen.findByText('Host does not support folder creation. Please upgrade.')).toBeTruthy(); + fireEvent.click(newFolder()); expect(screen.queryByRole('form', { name: 'New folder' })).toBeNull(); + fireEvent.click(choose()); await waitFor(() => expect(f.onSelect).toHaveBeenCalledWith('/home/sam')); + expect(f.createDirectory).not.toHaveBeenCalled(); +}); + +it('disables creation while offline, disabled, loading, or without a valid listing', async () => { + const f = fixture(); await ready(); + f.setState('disconnected'); expect(newFolder().disabled).toBe(true); + f.setState('connected'); await ready(); + f.rerender(f.client, true); expect(newFolder().disabled).toBe(true); + f.rerender(); await ready(); + const listing = deferred<ReturnType<typeof result>>(); + f.directories.mockImplementationOnce(() => listing.promise); + fireEvent.click(screen.getByRole('button', { name: 'Open alpha' })); + expect(newFolder().disabled).toBe(true); + await act(async () => listing.resolve(result('/home/sam/alpha'))); await ready(); + f.directories.mockRejectedValueOnce(new Error('Permission denied')); + fireEvent.click(screen.getByRole('button', { name: 'File system', exact: true })); + await screen.findByText('Can’t open this folder'); expect(newFolder().disabled).toBe(true); +}); + +it('invalidates every parent page/filter and alias on only the captured runtime and clears filters for hidden creation', async () => { + const f = fixture(); await ready(); + f.directories.mockImplementation(async params => ({ ...result(params.path === '~' ? '/home/sam' : params.path!, ['alpha']), has_more: !params.after, next_after: 'alpha' })); + const filter = screen.getByRole('textbox', { name: 'Filter folders by prefix' }) as HTMLInputElement; + fireEvent.change(filter, { target: { value: 'a' } }); await ready(); + fireEvent.click(screen.getByRole('checkbox', { name: 'Hidden folders' })); await ready(); + fireEvent.click(screen.getByRole('button', { name: 'Next folders' })); await ready(); + const cached = [ + ['directories', 'kuzco', '/home/sam', 'x', false, 'page-2'], + ['directories', 'kuzco', '~', '', true, ''], + ['directories', 'kuzco', '/alias', '', false, ''], + ]; + const other = ['directories', 'other-host', '/home/sam', '', false, '']; + // The daemon cleans paths but does not resolve symlinks: /alias stays /alias. + act(() => { for (const key of [...cached, other]) f.query.setQueryData(key, result(key[2] === '~' ? '/home/sam' : key[2] as string)); }); + submitFolder(nameFolder('.hidden')); + await screen.findByText('Folder created. Choose folder to use it.'); await ready(); + expect(f.createDirectory).toHaveBeenCalledExactlyOnceWith({ parent: '/home/sam', name: '.hidden' }); + expect(filter.value).toBe(''); + expect(screen.getByRole('checkbox', { name: 'Hidden folders' }).getAttribute('aria-checked')).toBe('false'); + expect(f.directories).toHaveBeenCalledWith(expect.objectContaining({ path: '/home/sam/.hidden', prefix: undefined, after: undefined, show_hidden: false }), expect.anything()); + for (const key of cached) expect(f.query.getQueryState(key)?.isInvalidated).toBe(true); + expect(f.query.getQueryState(other)?.isInvalidated).toBe(false); + expect(f.onSelect).not.toHaveBeenCalled(); +}); + +it('refreshes an actively viewed parent when stale creation succeeds without navigating or selecting', async () => { + const f = fixture(); await ready(); + const pending = deferred<{ path: string }>(); + f.createDirectory.mockImplementationOnce(() => pending.promise); + submitFolder(nameFolder()); + fireEvent.click(screen.getByRole('button', { name: 'sam', exact: true })); await ready(); + f.directories.mockImplementation(async params => result(params.path!, params.path === '/home/sam' ? ['alpha', 'project'] : [])); + await act(async () => pending.resolve({ path: '/home/sam/project' })); + await waitFor(() => expect(folder('project')).toBeTruthy()); + expect(screen.getByRole('navigation', { name: 'Folder path' }).textContent).not.toContain('project'); + expect(f.onSelect).not.toHaveBeenCalled(); + expect(screen.queryByText('Folder created. Choose folder to use it.')).toBeNull(); +}); + +it('keeps a stale failure out of a new creation form after navigation', async () => { + const f = fixture(); await ready(); + let reject!: (error: Error) => void; + f.createDirectory.mockImplementationOnce(() => new Promise((_resolve, fail) => { reject = fail; })); + submitFolder(nameFolder()); + fireEvent.click(screen.getByRole('button', { name: 'File system', exact: true })); await ready(); + const input = nameFolder('another'); + await act(async () => reject(new Error('Old request failed'))); + expect(screen.queryByText('Old request failed')).toBeNull(); expect(input.value).toBe('another'); + fireEvent.keyDown(input, { key: 'Enter', ctrlKey: true }); + expect(f.onSelect).not.toHaveBeenCalled(); expect(f.createDirectory).toHaveBeenCalledTimes(1); + submitFolder(input); await ready(); expect(f.createDirectory).toHaveBeenCalledTimes(2); +}); + +it('distinguishes successful creation from a failed destination listing and retries only the read', async () => { + const f = fixture(); await ready(); + f.directories.mockImplementation(async params => { if (params.path === '/home/sam/project') throw new Error('Read denied'); return result(params.path!); }); + submitFolder(nameFolder()); + await screen.findByText('Folder created, but its contents could not be loaded. Retry the listing; do not create it again.'); + expect(choose().disabled).toBe(true); expect(newFolder().disabled).toBe(true); + f.directories.mockImplementation(async params => result(params.path!)); + fireEvent.click(screen.getByRole('button', { name: 'Retry' })); await ready(); + expect(f.createDirectory).toHaveBeenCalledTimes(1); expect(f.onSelect).not.toHaveBeenCalled(); +}); + +it.each(['navigation', 'close', 'unmount', 'runtime', 'client', 'disconnect'] as const)('invalidates the original parent but ignores late creation after %s', async boundary => { + const f = fixture(); await ready(); + const pending = deferred<{ path: string }>(); + f.createDirectory.mockImplementationOnce(() => pending.promise); + const original = ['directories', 'kuzco', '/home/sam', 'cached', true, 'page']; + act(() => f.query.setQueryData(original, result('/home/sam'))); + submitFolder(nameFolder()); + if (boundary === 'navigation') fireEvent.click(screen.getByRole('button', { name: 'File system', exact: true })); + if (boundary === 'close') fireEvent.click(screen.getAllByRole('button', { name: 'Cancel', exact: true }).at(-1)!); + if (boundary === 'unmount') f.view.unmount(); + if (boundary === 'runtime') f.setRuntime('pacha'); + if (boundary === 'client') f.rerender({ ...f.client } as WhipClient); + if (boundary === 'disconnect') { f.setState('disconnected'); f.setState('connected'); } + await act(async () => pending.resolve({ path: '/home/sam/project' })); + await waitFor(() => expect(f.query.getQueryState(original)?.isInvalidated).toBe(true)); + expect(f.directories.mock.calls.some(([params]) => params.path === '/home/sam/project')).toBe(false); + expect(f.onSelect).not.toHaveBeenCalled(); + if (boundary !== 'unmount') expect(screen.queryByText('Folder created. Choose folder to use it.')).toBeNull(); +}); + it('revalidates an expired choice before confirming and rejects a late result after navigation', async () => { const f = fixture(); await ready(); const options = directoryOptions(f.client, { path: '/home/sam' }); diff --git a/packages/sdk/src/services.ts b/packages/sdk/src/services.ts index 950c5c950..3937405b5 100644 --- a/packages/sdk/src/services.ts +++ b/packages/sdk/src/services.ts @@ -1,14 +1,19 @@ -import { validate, type CommandResult, type ConfigurationUpdate, type HostAttentionParams, type HostDirectoryParams, type HostDirectoryPickParams, type MCPBrandIconsParams, type MCPImportApplyParams, type MCPImportCandidatesParams, type PermissionDecision, type PermissionDecisionResult, type ProviderCreateParams, type ProviderDisconnectParams, type ProviderKeySetup, type ProviderLoginBeginParams, type ProviderRemoveParams, type ProviderUpdateParams, type ProviderValidateParams } from '@whip/protocol'; +import { validate, type CommandResult, type ConfigurationUpdate, type HostAttentionParams, type HostDirectoryCreateParams, type HostDirectoryParams, type HostDirectoryPickParams, type MCPBrandIconsParams, type MCPImportApplyParams, type MCPImportCandidatesParams, type PermissionDecision, type PermissionDecisionResult, type ProviderCreateParams, type ProviderDisconnectParams, type ProviderKeySetup, type ProviderLoginBeginParams, type ProviderRemoveParams, type ProviderUpdateParams, type ProviderValidateParams } from '@whip/protocol'; import type { CallOptions, WhipClient } from './client.js'; import type { CommandOptions } from './command.js'; import { WhipError } from './errors.js'; -/** Host reads do not construct session actors or change client preferences. */ +/** Host services do not construct session actors or change client preferences. */ export class Host { constructor(private readonly client: WhipClient) {} directories(params: Partial<HostDirectoryParams> = {}, options: CallOptions = {}) { return this.client.call('host.directories.list', { limit: 64, ...params }, options); } + /** Creates one folder without starting a session or retrying the mutation. */ + createDirectory(params: HostDirectoryCreateParams, options: CallOptions = {}) { + return this.client.call('host.directory.create', params, options); + } + /** Opens the OS folder chooser on the execution host; rejects where the host has no desktop picker. */ pickDirectory(params: HostDirectoryPickParams = {}, options: CallOptions = {}) { return this.client.call('host.directory.pick', params, options); diff --git a/packages/sdk/test/services.test.ts b/packages/sdk/test/services.test.ts index 1e6a452f4..f05f5f67f 100644 --- a/packages/sdk/test/services.test.ts +++ b/packages/sdk/test/services.test.ts @@ -5,6 +5,53 @@ import { WhipClient } from '../src/client.js'; import { decodeBase64 } from '../src/util.js'; import { transportFixture } from './transport-fixture.js'; +test('host directory creation sends one typed request outside session command recovery', async t => { + const records: unknown[] = []; + const fixture = transportFixture({ request(request, connection) { + if (request.method === 'host.directory.create') connection.reply(request, { path: '/projects/new folder' }); + } }); + const client = new WhipClient({ endpoint: fixture.factory, clientId: 'client', reconnect: false, + recoveryStorage: { async list() { return []; }, async put(record) { records.push(record); }, async delete() {} } }); + t.after(() => client.close()); + await client.connect(); + assert.equal(client.supports('rpc', 'host.directory.create'), true); + assert.deepEqual(await client.host.createDirectory({ parent: '/projects', name: 'new folder' }), { path: '/projects/new folder' }); + assert.deepEqual(fixture.current.requests.at(-1)?.params, { parent: '/projects', name: 'new folder' }); + assert.deepEqual(fixture.current.requests.map(request => request.method), ['initialize', 'host.directory.create']); + assert.deepEqual(records, []); +}); + +test('host directory creation is unavailable on older hosts without sending a mutation', async t => { + const fixture = transportFixture(); + fixture.info.operations = fixture.info.operations!.filter(operation => operation.name !== 'host.directory.create'); + const client = new WhipClient({ endpoint: fixture.factory, clientId: 'client', reconnect: false }); + t.after(() => client.close()); + await client.connect(); + assert.equal(client.supports('rpc', 'host.directory.create'), false); + await assert.rejects(client.host.createDirectory({ parent: '/projects', name: 'new' }), { kind: 'unsupported_operation' }); + assert.deepEqual(fixture.current.requests.map(request => request.method), ['initialize']); +}); + +test('host directory creation does not replay a lost response after reconnect', async t => { + const records: unknown[] = []; + const fixture = transportFixture({ request(request, connection) { + if (request.method === 'host.directories.list') connection.reply(request, { path: '/projects', parent: '/', entries: [], has_more: false, truncated: false }); + // The create may have committed; deliberately lose its response. + } }); + const client = new WhipClient({ endpoint: fixture.factory, clientId: 'client', reconnect: false, + recoveryStorage: { async list() { return []; }, async put(record) { records.push(record); }, async delete() {} } }); + t.after(() => client.close()); + await client.connect(); + await assert.rejects(client.host.createDirectory({ parent: '/projects', name: 'new' }, { timeoutMs: 10 }), { kind: 'timeout' }); + fixture.current.fail(); + await client.connect(); + await client.host.directories({ path: '/projects' }); + assert.deepEqual(fixture.connections.flatMap(connection => connection.requests.map(request => request.method)), [ + 'initialize', 'host.directory.create', 'initialize', 'host.directories.list', + ]); + assert.deepEqual(records, []); +}); + const decision = { root_id: 'root', permission_id: 'permission', allow: true, command_id: 'decision-1', reason: '<tag> & café "quoted"' }; test('provider inventory, discovery and revision-checked disconnect stay outside command recovery', async t => { From f29bef231ce021d4b5c599e79f631bc30d60d68f Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Tue, 29 Sep 2026 11:26:03 -0700 Subject: [PATCH 18/67] fix(desktop): increase startup verification timeout from 30s to 60s The desktop release packaging step times out on slow macOS CI runners because a single 30s AbortSignal covers four sequential cold-daemon operations: connect, create session, submit a tool round trip, and snapshot. 30s is not enough headroom on a cold runner; bump to 60s. --- apps/desktop/scripts/startup.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/scripts/startup.mjs b/apps/desktop/scripts/startup.mjs index 1adabbd62..6d64e81fa 100644 --- a/apps/desktop/scripts/startup.mjs +++ b/apps/desktop/scripts/startup.mjs @@ -323,7 +323,7 @@ async function seedSession(fixture, executable, env, scheme) { const status = await fixtureStatus(executable, env); assert.equal(status.state, 'running'); client = createWhipClient({ endpoint: unixSocket(status.socket), clientId: randomUUID(), clientKind: 'automation' }); - const signal = AbortSignal.timeout(30_000); await client.connect({ signal }); + const signal = AbortSignal.timeout(60_000); await client.connect({ signal }); const created = await client.sessions.create({ cwd: path.join(fixture, 'work'), model: 'startup-model', provider: 'startup-provider' }).result({ signal }); assert.equal(created.status, 'succeeded'); const rootId = created.result.root_id; From 586becbbc8318a283cdd75ab84f596a864467433 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Tue, 29 Sep 2026 11:34:07 -0700 Subject: [PATCH 19/67] fix(daemon): gofumpt formatting in host_test.go --- internal/daemon/host_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/daemon/host_test.go b/internal/daemon/host_test.go index 94409afb6..0299f0a73 100644 --- a/internal/daemon/host_test.go +++ b/internal/daemon/host_test.go @@ -352,8 +352,10 @@ func TestHostDirectoryCreateRPC(t *testing.T) { func TestHostDirectoryCreateInvalidParams(t *testing.T) { parent := t.TempDir() - for _, raw := range []string{"", "null", "[]", "{", "{}", `{"parent":1,"name":"x"}`, `{"parent":"/tmp","name":false}`, - `{"parent":"/tmp","name":"x","extra":true}`, `{"parent":"/tmp","name":"x"} {}`} { + for _, raw := range []string{ + "", "null", "[]", "{", "{}", `{"parent":1,"name":"x"}`, `{"parent":"/tmp","name":false}`, + `{"parent":"/tmp","name":"x","extra":true}`, `{"parent":"/tmp","name":"x"} {}`, + } { _, rpcErr, handled := (&Server{}).handleHost(t.Context(), rpcMessage{Method: "host.directory.create", Params: json.RawMessage(raw)}) if !handled || rpcErr == nil || rpcErr.Code != -32602 { t.Fatalf("malformed params %q: %v handled=%v", raw, rpcErr, handled) From 68edf85dba1ef605b059d3377a48d3d283ac8188 Mon Sep 17 00:00:00 2001 From: Anish Thite <anish@inference.net> Date: Tue, 29 Sep 2026 11:34:35 -0700 Subject: [PATCH 20/67] feat(theme): add neon-city-dark and seti themes from PR #155 --- internal/theme/resolve_test.go | 2 +- internal/theme/themes/neon-city-dark.json | 45 +++ internal/theme/themes/seti.json | 45 +++ packages/ui/src/generated/theme-catalog.ts | 310 ++++++++++++++++++++- packages/ui/src/generated/themes.stylex.ts | 292 ++++++++++++------- 5 files changed, 585 insertions(+), 109 deletions(-) create mode 100644 internal/theme/themes/neon-city-dark.json create mode 100644 internal/theme/themes/seti.json diff --git a/internal/theme/resolve_test.go b/internal/theme/resolve_test.go index c81c89297..7babb4365 100644 --- a/internal/theme/resolve_test.go +++ b/internal/theme/resolve_test.go @@ -25,7 +25,7 @@ func TestAllShippedThemesMatchTerminal(t *testing.T) { t.Fatalf("browser %d themes; terminal %d", len(catalog), len(specs)) } // Guard the shipped inventory without encoding it into application logic. - if len(catalog) != 66 { + if len(catalog) != 68 { t.Fatalf("shipped inventory changed (%d); review theme parity fixtures", len(catalog)) } seen := map[string]bool{} diff --git a/internal/theme/themes/neon-city-dark.json b/internal/theme/themes/neon-city-dark.json new file mode 100644 index 000000000..3ff2c343b --- /dev/null +++ b/internal/theme/themes/neon-city-dark.json @@ -0,0 +1,45 @@ +{ + "name": "neon-city-dark", + "displayName": "Neon City Dark", + "dark": true, + "palette": { + "text": "#f8f8f2", + "muted": "#9aa7bd", + "faint": "#566078", + "primary": "#00e5ff", + "accent": "#ff4ecd", + "success": "#5cff9d", + "warning": "#ffe66d", + "error": "#ff5370", + "info": "#7c8cff", + "link": "#00e5ff", + "emphasis": "#ff9f43", + "onPrimary": "#090b18", + "border": "#303854", + "borderFocus": "#00e5ff", + "bg": "#090b18", + "diffAdd": "#123829", + "diffDel": "#3d1628" + }, + "surfaces": { + "panel": "#0e1224", + "element": "#141a30", + "hover": "#202844" + }, + "syntax": { + "keyword": "#ff4ecd", + "string": "#5cff9d", + "number": "#ff9f43", + "comment": "#69738f", + "function": "#00e5ff", + "type": "#ffe66d", + "operator": "#7c8cff", + "punctuation": "#f8f8f2" + }, + "markdown": { + "heading": "#ff4ecd", + "strong": "#ffe66d", + "code": "#5cff9d", + "quote": "#9aa7bd" + } +} diff --git a/internal/theme/themes/seti.json b/internal/theme/themes/seti.json new file mode 100644 index 000000000..2417eb725 --- /dev/null +++ b/internal/theme/themes/seti.json @@ -0,0 +1,45 @@ +{ + "name": "seti", + "displayName": "Seti", + "dark": true, + "palette": { + "text": "#d4d7d6", + "muted": "#8b9494", + "faint": "#596364", + "primary": "#55b5db", + "accent": "#a074c4", + "success": "#9fca56", + "warning": "#e6cd69", + "error": "#cd3f45", + "info": "#55b5db", + "link": "#55b5db", + "emphasis": "#e6cd69", + "onPrimary": "#151718", + "border": "#3b4446", + "borderFocus": "#55b5db", + "bg": "#151718", + "diffAdd": "#263829", + "diffDel": "#3d2428" + }, + "surfaces": { + "panel": "#1b1f20", + "element": "#202526", + "hover": "#293032" + }, + "syntax": { + "keyword": "#a074c4", + "string": "#9fca56", + "number": "#e6cd69", + "comment": "#6d7a7b", + "function": "#55b5db", + "type": "#db7b55", + "operator": "#d4d7d6", + "punctuation": "#8b9494" + }, + "markdown": { + "heading": "#55b5db", + "strong": "#e6cd69", + "code": "#9fca56", + "quote": "#8b9494" + } +} diff --git a/packages/ui/src/generated/theme-catalog.ts b/packages/ui/src/generated/theme-catalog.ts index 04ffed920..e90478f32 100644 --- a/packages/ui/src/generated/theme-catalog.ts +++ b/packages/ui/src/generated/theme-catalog.ts @@ -6043,6 +6043,160 @@ export const themeCatalog: readonly ThemeDefinition[] = [ "type": "#66d9ef" } }, + { + "code": { + "background": "#141a30", + "foreground": "#f8f8f2", + "tokens": { + "Background": { + "background": "#141a30", + "bold": false, + "color": "#f8f8f2", + "italic": false, + "underline": false + }, + "Comment": { + "background": "#141a30", + "bold": false, + "color": "#69738f", + "italic": true, + "underline": false + }, + "Error": { + "background": "#141a30", + "bold": false, + "color": "#ff5370", + "italic": false, + "underline": false + }, + "GenericDeleted": { + "background": "#141a30", + "bold": false, + "color": "#ff5370", + "italic": false, + "underline": false + }, + "GenericInserted": { + "background": "#141a30", + "bold": false, + "color": "#5cff9d", + "italic": false, + "underline": false + }, + "Keyword": { + "background": "#141a30", + "bold": false, + "color": "#ff4ecd", + "italic": false, + "underline": false + }, + "KeywordType": { + "background": "#141a30", + "bold": false, + "color": "#ffe66d", + "italic": false, + "underline": false + }, + "LiteralNumber": { + "background": "#141a30", + "bold": false, + "color": "#ff9f43", + "italic": false, + "underline": false + }, + "LiteralString": { + "background": "#141a30", + "bold": false, + "color": "#5cff9d", + "italic": false, + "underline": false + }, + "NameBuiltin": { + "background": "#141a30", + "bold": false, + "color": "#00e5ff", + "italic": false, + "underline": false + }, + "NameClass": { + "background": "#141a30", + "bold": true, + "color": "#ffe66d", + "italic": false, + "underline": false + }, + "NameFunction": { + "background": "#141a30", + "bold": false, + "color": "#00e5ff", + "italic": false, + "underline": false + }, + "Operator": { + "background": "#141a30", + "bold": false, + "color": "#7c8cff", + "italic": false, + "underline": false + }, + "Punctuation": { + "background": "#141a30", + "bold": false, + "color": "#f8f8f2", + "italic": false, + "underline": false + }, + "Text": { + "background": "#141a30", + "bold": false, + "color": "#f8f8f2", + "italic": false, + "underline": false + } + } + }, + "colors": { + "accent": "#ff4ecd", + "background": "#090b18", + "border": "#303854", + "borderFocus": "#00e5ff", + "diffAdd": "#123829", + "diffDel": "#3d1628", + "element": "#141a30", + "emphasis": "#ff9f43", + "error": "#ff5370", + "faint": "#566078", + "foreground": "#f8f8f2", + "hover": "#202844", + "info": "#7c8cff", + "link": "#00e5ff", + "muted": "#9aa7bd", + "onPrimary": "#090b18", + "panel": "#0e1224", + "primary": "#00e5ff", + "success": "#5cff9d", + "warning": "#ffe66d" + }, + "dark": true, + "id": "neon-city-dark", + "markdown": { + "code": "#5cff9d", + "heading": "#ff4ecd", + "quote": "#9aa7bd", + "strong": "#ffe66d" + }, + "name": "Neon City Dark", + "syntax": { + "comment": "#69738f", + "function": "#00e5ff", + "keyword": "#ff4ecd", + "number": "#ff9f43", + "operator": "#7c8cff", + "punctuation": "#f8f8f2", + "string": "#5cff9d", + "type": "#ffe66d" + } + }, { "code": { "background": "#0b253a", @@ -8507,6 +8661,160 @@ export const themeCatalog: readonly ThemeDefinition[] = [ "type": "#56949f" } }, + { + "code": { + "background": "#202526", + "foreground": "#d4d7d6", + "tokens": { + "Background": { + "background": "#202526", + "bold": false, + "color": "#d4d7d6", + "italic": false, + "underline": false + }, + "Comment": { + "background": "#202526", + "bold": false, + "color": "#6d7a7b", + "italic": true, + "underline": false + }, + "Error": { + "background": "#202526", + "bold": false, + "color": "#cd3f45", + "italic": false, + "underline": false + }, + "GenericDeleted": { + "background": "#202526", + "bold": false, + "color": "#cd3f45", + "italic": false, + "underline": false + }, + "GenericInserted": { + "background": "#202526", + "bold": false, + "color": "#9fca56", + "italic": false, + "underline": false + }, + "Keyword": { + "background": "#202526", + "bold": false, + "color": "#a074c4", + "italic": false, + "underline": false + }, + "KeywordType": { + "background": "#202526", + "bold": false, + "color": "#db7b55", + "italic": false, + "underline": false + }, + "LiteralNumber": { + "background": "#202526", + "bold": false, + "color": "#e6cd69", + "italic": false, + "underline": false + }, + "LiteralString": { + "background": "#202526", + "bold": false, + "color": "#9fca56", + "italic": false, + "underline": false + }, + "NameBuiltin": { + "background": "#202526", + "bold": false, + "color": "#55b5db", + "italic": false, + "underline": false + }, + "NameClass": { + "background": "#202526", + "bold": true, + "color": "#db7b55", + "italic": false, + "underline": false + }, + "NameFunction": { + "background": "#202526", + "bold": false, + "color": "#55b5db", + "italic": false, + "underline": false + }, + "Operator": { + "background": "#202526", + "bold": false, + "color": "#d4d7d6", + "italic": false, + "underline": false + }, + "Punctuation": { + "background": "#202526", + "bold": false, + "color": "#8b9494", + "italic": false, + "underline": false + }, + "Text": { + "background": "#202526", + "bold": false, + "color": "#d4d7d6", + "italic": false, + "underline": false + } + } + }, + "colors": { + "accent": "#a074c4", + "background": "#151718", + "border": "#3b4446", + "borderFocus": "#55b5db", + "diffAdd": "#263829", + "diffDel": "#3d2428", + "element": "#202526", + "emphasis": "#e6cd69", + "error": "#cd3f45", + "faint": "#596364", + "foreground": "#d4d7d6", + "hover": "#293032", + "info": "#55b5db", + "link": "#55b5db", + "muted": "#8b9494", + "onPrimary": "#151718", + "panel": "#1b1f20", + "primary": "#55b5db", + "success": "#9fca56", + "warning": "#e6cd69" + }, + "dark": true, + "id": "seti", + "markdown": { + "code": "#9fca56", + "heading": "#55b5db", + "quote": "#8b9494", + "strong": "#e6cd69" + }, + "name": "Seti", + "syntax": { + "comment": "#6d7a7b", + "function": "#55b5db", + "keyword": "#a074c4", + "number": "#e6cd69", + "operator": "#d4d7d6", + "punctuation": "#8b9494", + "string": "#9fca56", + "type": "#db7b55" + } + }, { "code": { "background": "#073642", @@ -10203,5 +10511,5 @@ export const themeCatalog: readonly ThemeDefinition[] = [ }, ]; -export const themeIds = ["light","dark","aura","aura-light","ayu","ayu-light","carbonfox","carbonfox-light","catppuccin","catppuccin-frappe","catppuccin-frappe-light","catppuccin-light","catppuccin-macchiato","catppuccin-macchiato-light","claude-code","cobalt2","cobalt2-light","cursor","cursor-light","dracula","dracula-light","everforest","everforest-light","flexoki","flexoki-light","github","github-light","gruvbox","gruvbox-light","kanagawa","kanagawa-light","material","material-light","matrix","matrix-light","mercury","mercury-light","monokai","monokai-light","nightowl","nightowl-light","nord","nord-light","one-dark","one-dark-light","opencode","opencode-light","orng","orng-light","osaka-jade","osaka-jade-light","palenight","palenight-light","rosepine","rosepine-light","solarized","solarized-light","synthwave84","synthwave84-light","tokyonight","tokyonight-light","vercel","vercel-light","vesper","zenburn","zenburn-light"] as const; +export const themeIds = ["light","dark","aura","aura-light","ayu","ayu-light","carbonfox","carbonfox-light","catppuccin","catppuccin-frappe","catppuccin-frappe-light","catppuccin-light","catppuccin-macchiato","catppuccin-macchiato-light","claude-code","cobalt2","cobalt2-light","cursor","cursor-light","dracula","dracula-light","everforest","everforest-light","flexoki","flexoki-light","github","github-light","gruvbox","gruvbox-light","kanagawa","kanagawa-light","material","material-light","matrix","matrix-light","mercury","mercury-light","monokai","monokai-light","neon-city-dark","nightowl","nightowl-light","nord","nord-light","one-dark","one-dark-light","opencode","opencode-light","orng","orng-light","osaka-jade","osaka-jade-light","palenight","palenight-light","rosepine","rosepine-light","seti","solarized","solarized-light","synthwave84","synthwave84-light","tokyonight","tokyonight-light","vercel","vercel-light","vesper","zenburn","zenburn-light"] as const; export type BuiltinThemeID = (typeof themeIds)[number]; diff --git a/packages/ui/src/generated/themes.stylex.ts b/packages/ui/src/generated/themes.stylex.ts index 7674bc551..c326b07dd 100644 --- a/packages/ui/src/generated/themes.stylex.ts +++ b/packages/ui/src/generated/themes.stylex.ts @@ -1485,6 +1485,44 @@ const theme38markdown = createTheme(markdown, { "strong": "#fd971f" }); const theme39colors = createTheme(colors, { + "accent": "#ff4ecd", + "background": "#090b18", + "border": "#303854", + "borderFocus": "#00e5ff", + "diffAdd": "#123829", + "diffDel": "#3d1628", + "element": "#141a30", + "emphasis": "#ff9f43", + "error": "#ff5370", + "faint": "#566078", + "foreground": "#f8f8f2", + "hover": "#202844", + "info": "#7c8cff", + "link": "#00e5ff", + "muted": "#9aa7bd", + "onPrimary": "#090b18", + "panel": "#0e1224", + "primary": "#00e5ff", + "success": "#5cff9d", + "warning": "#ffe66d" +}); +const theme39syntax = createTheme(syntax, { + "comment": "#69738f", + "function": "#00e5ff", + "keyword": "#ff4ecd", + "number": "#ff9f43", + "operator": "#7c8cff", + "punctuation": "#f8f8f2", + "string": "#5cff9d", + "type": "#ffe66d" +}); +const theme39markdown = createTheme(markdown, { + "code": "#5cff9d", + "heading": "#ff4ecd", + "quote": "#9aa7bd", + "strong": "#ffe66d" +}); +const theme40colors = createTheme(colors, { "accent": "#c792ea", "background": "#011627", "border": "#5f7e97", @@ -1506,7 +1544,7 @@ const theme39colors = createTheme(colors, { "success": "#c5e478", "warning": "#ecc48d" }); -const theme39syntax = createTheme(syntax, { +const theme40syntax = createTheme(syntax, { "comment": "#637777", "function": "#82aaff", "keyword": "#c792ea", @@ -1516,13 +1554,13 @@ const theme39syntax = createTheme(syntax, { "string": "#ecc48d", "type": "#c5e478" }); -const theme39markdown = createTheme(markdown, { +const theme40markdown = createTheme(markdown, { "code": "#c5e478", "heading": "#82aaff", "quote": "#5f7e97", "strong": "#ecc48d" }); -const theme40colors = createTheme(colors, { +const theme41colors = createTheme(colors, { "accent": "#c792ea", "background": "#011627", "border": "#5f7e97", @@ -1544,7 +1582,7 @@ const theme40colors = createTheme(colors, { "success": "#c5e478", "warning": "#ecc48d" }); -const theme40syntax = createTheme(syntax, { +const theme41syntax = createTheme(syntax, { "comment": "#637777", "function": "#82aaff", "keyword": "#c792ea", @@ -1554,13 +1592,13 @@ const theme40syntax = createTheme(syntax, { "string": "#ecc48d", "type": "#c5e478" }); -const theme40markdown = createTheme(markdown, { +const theme41markdown = createTheme(markdown, { "code": "#c5e478", "heading": "#82aaff", "quote": "#5f7e97", "strong": "#ecc48d" }); -const theme41colors = createTheme(colors, { +const theme42colors = createTheme(colors, { "accent": "#8fbcbb", "background": "#2e3440", "border": "#434c5e", @@ -1582,7 +1620,7 @@ const theme41colors = createTheme(colors, { "success": "#a3be8c", "warning": "#d08770" }); -const theme41syntax = createTheme(syntax, { +const theme42syntax = createTheme(syntax, { "comment": "#8b95a7", "function": "#88c0d0", "keyword": "#81a1c1", @@ -1592,13 +1630,13 @@ const theme41syntax = createTheme(syntax, { "string": "#a3be8c", "type": "#8fbcbb" }); -const theme41markdown = createTheme(markdown, { +const theme42markdown = createTheme(markdown, { "code": "#a3be8c", "heading": "#88c0d0", "quote": "#8b95a7", "strong": "#ebcb8b" }); -const theme42colors = createTheme(colors, { +const theme43colors = createTheme(colors, { "accent": "#8fbcbb", "background": "#eceff4", "border": "#4c566a", @@ -1620,7 +1658,7 @@ const theme42colors = createTheme(colors, { "success": "#a3be8c", "warning": "#d08770" }); -const theme42syntax = createTheme(syntax, { +const theme43syntax = createTheme(syntax, { "comment": "#4c566a", "function": "#88c0d0", "keyword": "#81a1c1", @@ -1630,13 +1668,13 @@ const theme42syntax = createTheme(syntax, { "string": "#a3be8c", "type": "#8fbcbb" }); -const theme42markdown = createTheme(markdown, { +const theme43markdown = createTheme(markdown, { "code": "#a3be8c", "heading": "#5e81ac", "quote": "#4c566a", "strong": "#ebcb8b" }); -const theme43colors = createTheme(colors, { +const theme44colors = createTheme(colors, { "accent": "#56b6c2", "background": "#282c34", "border": "#393f4a", @@ -1658,7 +1696,7 @@ const theme43colors = createTheme(colors, { "success": "#98c379", "warning": "#e5c07b" }); -const theme43syntax = createTheme(syntax, { +const theme44syntax = createTheme(syntax, { "comment": "#5c6370", "function": "#61afef", "keyword": "#c678dd", @@ -1668,13 +1706,13 @@ const theme43syntax = createTheme(syntax, { "string": "#98c379", "type": "#e5c07b" }); -const theme43markdown = createTheme(markdown, { +const theme44markdown = createTheme(markdown, { "code": "#98c379", "heading": "#c678dd", "quote": "#5c6370", "strong": "#d19a66" }); -const theme44colors = createTheme(colors, { +const theme45colors = createTheme(colors, { "accent": "#0184bc", "background": "#fafafa", "border": "#d1d1d2", @@ -1696,7 +1734,7 @@ const theme44colors = createTheme(colors, { "success": "#50a14f", "warning": "#c18401" }); -const theme44syntax = createTheme(syntax, { +const theme45syntax = createTheme(syntax, { "comment": "#a0a1a7", "function": "#4078f2", "keyword": "#a626a4", @@ -1706,13 +1744,13 @@ const theme44syntax = createTheme(syntax, { "string": "#50a14f", "type": "#c18401" }); -const theme44markdown = createTheme(markdown, { +const theme45markdown = createTheme(markdown, { "code": "#50a14f", "heading": "#a626a4", "quote": "#a0a1a7", "strong": "#986801" }); -const theme45colors = createTheme(colors, { +const theme46colors = createTheme(colors, { "accent": "#9d7cd8", "background": "#0a0a0a", "border": "#484848", @@ -1734,7 +1772,7 @@ const theme45colors = createTheme(colors, { "success": "#7fd88f", "warning": "#f5a742" }); -const theme45syntax = createTheme(syntax, { +const theme46syntax = createTheme(syntax, { "comment": "#808080", "function": "#fab283", "keyword": "#9d7cd8", @@ -1744,13 +1782,13 @@ const theme45syntax = createTheme(syntax, { "string": "#7fd88f", "type": "#e5c07b" }); -const theme45markdown = createTheme(markdown, { +const theme46markdown = createTheme(markdown, { "code": "#7fd88f", "heading": "#9d7cd8", "quote": "#e5c07b", "strong": "#f5a742" }); -const theme46colors = createTheme(colors, { +const theme47colors = createTheme(colors, { "accent": "#d68c27", "background": "#ffffff", "border": "#b8b8b8", @@ -1772,7 +1810,7 @@ const theme46colors = createTheme(colors, { "success": "#3d9a57", "warning": "#d68c27" }); -const theme46syntax = createTheme(syntax, { +const theme47syntax = createTheme(syntax, { "comment": "#8a8a8a", "function": "#3b7dd8", "keyword": "#d68c27", @@ -1782,13 +1820,13 @@ const theme46syntax = createTheme(syntax, { "string": "#3d9a57", "type": "#b0851f" }); -const theme46markdown = createTheme(markdown, { +const theme47markdown = createTheme(markdown, { "code": "#3d9a57", "heading": "#d68c27", "quote": "#b0851f", "strong": "#d68c27" }); -const theme47colors = createTheme(colors, { +const theme48colors = createTheme(colors, { "accent": "#fff7f1", "background": "#0a0a0a", "border": "#ec5b2b", @@ -1810,7 +1848,7 @@ const theme47colors = createTheme(colors, { "success": "#6ba1e6", "warning": "#ec5b2b" }); -const theme47syntax = createTheme(syntax, { +const theme48syntax = createTheme(syntax, { "comment": "#808080", "function": "#ee7948", "keyword": "#ec5b2b", @@ -1820,13 +1858,13 @@ const theme47syntax = createTheme(syntax, { "string": "#6ba1e6", "type": "#e5c07b" }); -const theme47markdown = createTheme(markdown, { +const theme48markdown = createTheme(markdown, { "code": "#6ba1e6", "heading": "#ec5b2b", "quote": "#fff7f1", "strong": "#ee7948" }); -const theme48colors = createTheme(colors, { +const theme49colors = createTheme(colors, { "accent": "#c94d24", "background": "#ffffff", "border": "#ec5b2b", @@ -1848,7 +1886,7 @@ const theme48colors = createTheme(colors, { "success": "#0062d1", "warning": "#ec5b2b" }); -const theme48syntax = createTheme(syntax, { +const theme49syntax = createTheme(syntax, { "comment": "#8a8a8a", "function": "#c94d24", "keyword": "#ec5b2b", @@ -1858,13 +1896,13 @@ const theme48syntax = createTheme(syntax, { "string": "#0062d1", "type": "#b0851f" }); -const theme48markdown = createTheme(markdown, { +const theme49markdown = createTheme(markdown, { "code": "#0062d1", "heading": "#ec5b2b", "quote": "#b0851f", "strong": "#ec5b2b" }); -const theme49colors = createTheme(colors, { +const theme50colors = createTheme(colors, { "accent": "#549e6a", "background": "#111c18", "border": "#3d4a44", @@ -1886,7 +1924,7 @@ const theme49colors = createTheme(colors, { "success": "#549e6a", "warning": "#e5c736" }); -const theme49syntax = createTheme(syntax, { +const theme50syntax = createTheme(syntax, { "comment": "#53685b", "function": "#509475", "keyword": "#2dd5b7", @@ -1896,13 +1934,13 @@ const theme49syntax = createTheme(syntax, { "string": "#63b07a", "type": "#549e6a" }); -const theme49markdown = createTheme(markdown, { +const theme50markdown = createTheme(markdown, { "code": "#63b07a", "heading": "#2dd5b7", "quote": "#53685b", "strong": "#c1c497" }); -const theme50colors = createTheme(colors, { +const theme51colors = createTheme(colors, { "accent": "#3d7a52", "background": "#f6f5dd", "border": "#a8a78c", @@ -1924,7 +1962,7 @@ const theme50colors = createTheme(colors, { "success": "#3d7a52", "warning": "#b5a020" }); -const theme50syntax = createTheme(syntax, { +const theme51syntax = createTheme(syntax, { "comment": "#53685b", "function": "#3d7560", "keyword": "#1faa90", @@ -1934,13 +1972,13 @@ const theme50syntax = createTheme(syntax, { "string": "#3d7a52", "type": "#3d7a52" }); -const theme50markdown = createTheme(markdown, { +const theme51markdown = createTheme(markdown, { "code": "#3d7a52", "heading": "#1faa90", "quote": "#53685b", "strong": "#111c18" }); -const theme51colors = createTheme(colors, { +const theme52colors = createTheme(colors, { "accent": "#89ddff", "background": "#292d3e", "border": "#32364a", @@ -1962,7 +2000,7 @@ const theme51colors = createTheme(colors, { "success": "#c3e88d", "warning": "#ffcb6b" }); -const theme51syntax = createTheme(syntax, { +const theme52syntax = createTheme(syntax, { "comment": "#676e95", "function": "#82aaff", "keyword": "#c792ea", @@ -1972,13 +2010,13 @@ const theme51syntax = createTheme(syntax, { "string": "#c3e88d", "type": "#ffcb6b" }); -const theme51markdown = createTheme(markdown, { +const theme52markdown = createTheme(markdown, { "code": "#c3e88d", "heading": "#c792ea", "quote": "#676e95", "strong": "#f78c6c" }); -const theme52colors = createTheme(colors, { +const theme53colors = createTheme(colors, { "accent": "#00acc1", "background": "#fafafa", "border": "#e0e0e0", @@ -2000,7 +2038,7 @@ const theme52colors = createTheme(colors, { "success": "#91b859", "warning": "#ffb300" }); -const theme52syntax = createTheme(syntax, { +const theme53syntax = createTheme(syntax, { "comment": "#8796b0", "function": "#4976eb", "keyword": "#a854f2", @@ -2010,13 +2048,13 @@ const theme52syntax = createTheme(syntax, { "string": "#91b859", "type": "#ffb300" }); -const theme52markdown = createTheme(markdown, { +const theme53markdown = createTheme(markdown, { "code": "#91b859", "heading": "#a854f2", "quote": "#8796b0", "strong": "#f4511e" }); -const theme53colors = createTheme(colors, { +const theme54colors = createTheme(colors, { "accent": "#ebbcba", "background": "#191724", "border": "#403d52", @@ -2038,7 +2076,7 @@ const theme53colors = createTheme(colors, { "success": "#31748f", "warning": "#f6c177" }); -const theme53syntax = createTheme(syntax, { +const theme54syntax = createTheme(syntax, { "comment": "#6e6a86", "function": "#ebbcba", "keyword": "#31748f", @@ -2048,13 +2086,13 @@ const theme53syntax = createTheme(syntax, { "string": "#f6c177", "type": "#9ccfd8" }); -const theme53markdown = createTheme(markdown, { +const theme54markdown = createTheme(markdown, { "code": "#31748f", "heading": "#c4a7e7", "quote": "#6e6a86", "strong": "#eb6f92" }); -const theme54colors = createTheme(colors, { +const theme55colors = createTheme(colors, { "accent": "#d7827e", "background": "#faf4ed", "border": "#dfdad9", @@ -2076,7 +2114,7 @@ const theme54colors = createTheme(colors, { "success": "#286983", "warning": "#ea9d34" }); -const theme54syntax = createTheme(syntax, { +const theme55syntax = createTheme(syntax, { "comment": "#9893a5", "function": "#d7827e", "keyword": "#286983", @@ -2086,13 +2124,51 @@ const theme54syntax = createTheme(syntax, { "string": "#ea9d34", "type": "#56949f" }); -const theme54markdown = createTheme(markdown, { +const theme55markdown = createTheme(markdown, { "code": "#286983", "heading": "#907aa9", "quote": "#9893a5", "strong": "#b4637a" }); -const theme55colors = createTheme(colors, { +const theme56colors = createTheme(colors, { + "accent": "#a074c4", + "background": "#151718", + "border": "#3b4446", + "borderFocus": "#55b5db", + "diffAdd": "#263829", + "diffDel": "#3d2428", + "element": "#202526", + "emphasis": "#e6cd69", + "error": "#cd3f45", + "faint": "#596364", + "foreground": "#d4d7d6", + "hover": "#293032", + "info": "#55b5db", + "link": "#55b5db", + "muted": "#8b9494", + "onPrimary": "#151718", + "panel": "#1b1f20", + "primary": "#55b5db", + "success": "#9fca56", + "warning": "#e6cd69" +}); +const theme56syntax = createTheme(syntax, { + "comment": "#6d7a7b", + "function": "#55b5db", + "keyword": "#a074c4", + "number": "#e6cd69", + "operator": "#d4d7d6", + "punctuation": "#8b9494", + "string": "#9fca56", + "type": "#db7b55" +}); +const theme56markdown = createTheme(markdown, { + "code": "#9fca56", + "heading": "#55b5db", + "quote": "#8b9494", + "strong": "#e6cd69" +}); +const theme57colors = createTheme(colors, { "accent": "#2aa198", "background": "#002b36", "border": "#073642", @@ -2114,7 +2190,7 @@ const theme55colors = createTheme(colors, { "success": "#859900", "warning": "#b58900" }); -const theme55syntax = createTheme(syntax, { +const theme57syntax = createTheme(syntax, { "comment": "#586e75", "function": "#268bd2", "keyword": "#859900", @@ -2124,13 +2200,13 @@ const theme55syntax = createTheme(syntax, { "string": "#2aa198", "type": "#b58900" }); -const theme55markdown = createTheme(markdown, { +const theme57markdown = createTheme(markdown, { "code": "#859900", "heading": "#268bd2", "quote": "#586e75", "strong": "#cb4b16" }); -const theme56colors = createTheme(colors, { +const theme58colors = createTheme(colors, { "accent": "#2aa198", "background": "#fdf6e3", "border": "#eee8d5", @@ -2152,7 +2228,7 @@ const theme56colors = createTheme(colors, { "success": "#859900", "warning": "#b58900" }); -const theme56syntax = createTheme(syntax, { +const theme58syntax = createTheme(syntax, { "comment": "#93a1a1", "function": "#268bd2", "keyword": "#859900", @@ -2162,13 +2238,13 @@ const theme56syntax = createTheme(syntax, { "string": "#2aa198", "type": "#b58900" }); -const theme56markdown = createTheme(markdown, { +const theme58markdown = createTheme(markdown, { "code": "#859900", "heading": "#268bd2", "quote": "#93a1a1", "strong": "#cb4b16" }); -const theme57colors = createTheme(colors, { +const theme59colors = createTheme(colors, { "accent": "#b084eb", "background": "#262335", "border": "#495495", @@ -2190,7 +2266,7 @@ const theme57colors = createTheme(colors, { "success": "#72f1b8", "warning": "#fede5d" }); -const theme57syntax = createTheme(syntax, { +const theme59syntax = createTheme(syntax, { "comment": "#848bbd", "function": "#ff8b39", "keyword": "#ff7edb", @@ -2200,13 +2276,13 @@ const theme57syntax = createTheme(syntax, { "string": "#fede5d", "type": "#36f9f6" }); -const theme57markdown = createTheme(markdown, { +const theme59markdown = createTheme(markdown, { "code": "#72f1b8", "heading": "#ff7edb", "quote": "#848bbd", "strong": "#ff8b39" }); -const theme58colors = createTheme(colors, { +const theme60colors = createTheme(colors, { "accent": "#9c27b0", "background": "#fafafa", "border": "#e0e0e0", @@ -2228,7 +2304,7 @@ const theme58colors = createTheme(colors, { "success": "#4caf50", "warning": "#ff9800" }); -const theme58syntax = createTheme(syntax, { +const theme60syntax = createTheme(syntax, { "comment": "#5c5c8a", "function": "#ff5722", "keyword": "#e91e63", @@ -2238,13 +2314,13 @@ const theme58syntax = createTheme(syntax, { "string": "#ff9800", "type": "#00bcd4" }); -const theme58markdown = createTheme(markdown, { +const theme60markdown = createTheme(markdown, { "code": "#4caf50", "heading": "#e91e63", "quote": "#5c5c8a", "strong": "#ff5722" }); -const theme59colors = createTheme(colors, { +const theme61colors = createTheme(colors, { "accent": "#ff966c", "background": "#1a1b26", "border": "#737aa2", @@ -2266,7 +2342,7 @@ const theme59colors = createTheme(colors, { "success": "#c3e88d", "warning": "#ff966c" }); -const theme59syntax = createTheme(syntax, { +const theme61syntax = createTheme(syntax, { "comment": "#828bb8", "function": "#82aaff", "keyword": "#c099ff", @@ -2276,13 +2352,13 @@ const theme59syntax = createTheme(syntax, { "string": "#c3e88d", "type": "#ffc777" }); -const theme59markdown = createTheme(markdown, { +const theme61markdown = createTheme(markdown, { "code": "#c3e88d", "heading": "#c099ff", "quote": "#ffc777", "strong": "#ff966c" }); -const theme60colors = createTheme(colors, { +const theme62colors = createTheme(colors, { "accent": "#b15c00", "background": "#e1e2e7", "border": "#737a8c", @@ -2304,7 +2380,7 @@ const theme60colors = createTheme(colors, { "success": "#587539", "warning": "#b15c00" }); -const theme60syntax = createTheme(syntax, { +const theme62syntax = createTheme(syntax, { "comment": "#8990a3", "function": "#2e7de9", "keyword": "#9854f1", @@ -2314,13 +2390,13 @@ const theme60syntax = createTheme(syntax, { "string": "#587539", "type": "#8c6c3e" }); -const theme60markdown = createTheme(markdown, { +const theme62markdown = createTheme(markdown, { "code": "#587539", "heading": "#9854f1", "quote": "#8c6c3e", "strong": "#b15c00" }); -const theme61colors = createTheme(colors, { +const theme63colors = createTheme(colors, { "accent": "#8e4ec6", "background": "#000000", "border": "#1f1f1f", @@ -2342,7 +2418,7 @@ const theme61colors = createTheme(colors, { "success": "#46a758", "warning": "#ffb224" }); -const theme61syntax = createTheme(syntax, { +const theme63syntax = createTheme(syntax, { "comment": "#878787", "function": "#bf7af0", "keyword": "#f75590", @@ -2352,13 +2428,13 @@ const theme61syntax = createTheme(syntax, { "string": "#63c46d", "type": "#0ac7ac" }); -const theme61markdown = createTheme(markdown, { +const theme63markdown = createTheme(markdown, { "code": "#63c46d", "heading": "#bf7af0", "quote": "#878787", "strong": "#f75590" }); -const theme62colors = createTheme(colors, { +const theme64colors = createTheme(colors, { "accent": "#8e4ec6", "background": "#ffffff", "border": "#eaeaea", @@ -2380,7 +2456,7 @@ const theme62colors = createTheme(colors, { "success": "#388e3c", "warning": "#ff9500" }); -const theme62syntax = createTheme(syntax, { +const theme64syntax = createTheme(syntax, { "comment": "#888888", "function": "#8e4ec6", "keyword": "#e93d82", @@ -2390,13 +2466,13 @@ const theme62syntax = createTheme(syntax, { "string": "#46a758", "type": "#12a594" }); -const theme62markdown = createTheme(markdown, { +const theme64markdown = createTheme(markdown, { "code": "#46a758", "heading": "#8e4ec6", "quote": "#666666", "strong": "#e93d82" }); -const theme63colors = createTheme(colors, { +const theme65colors = createTheme(colors, { "accent": "#ffc799", "background": "#101010", "border": "#282828", @@ -2418,7 +2494,7 @@ const theme63colors = createTheme(colors, { "success": "#99ffe4", "warning": "#ffc799" }); -const theme63syntax = createTheme(syntax, { +const theme65syntax = createTheme(syntax, { "comment": "#8b8b8b", "function": "#ffc799", "keyword": "#a0a0a0", @@ -2428,13 +2504,13 @@ const theme63syntax = createTheme(syntax, { "string": "#99ffe4", "type": "#ffc799" }); -const theme63markdown = createTheme(markdown, { +const theme65markdown = createTheme(markdown, { "code": "#a0a0a0", "heading": "#ffc799", "quote": "#a0a0a0", "strong": "#ffc799" }); -const theme64colors = createTheme(colors, { +const theme66colors = createTheme(colors, { "accent": "#93e0e3", "background": "#3f3f3f", "border": "#5f5f5f", @@ -2456,7 +2532,7 @@ const theme64colors = createTheme(colors, { "success": "#7f9f7f", "warning": "#f0dfaf" }); -const theme64syntax = createTheme(syntax, { +const theme66syntax = createTheme(syntax, { "comment": "#7f9f7f", "function": "#8cd0d3", "keyword": "#f0dfaf", @@ -2466,13 +2542,13 @@ const theme64syntax = createTheme(syntax, { "string": "#cc9393", "type": "#93e0e3" }); -const theme64markdown = createTheme(markdown, { +const theme66markdown = createTheme(markdown, { "code": "#7f9f7f", "heading": "#f0dfaf", "quote": "#9f9f9f", "strong": "#dfaf8f" }); -const theme65colors = createTheme(colors, { +const theme67colors = createTheme(colors, { "accent": "#5f8f8f", "background": "#ffffef", "border": "#d0d0c0", @@ -2494,7 +2570,7 @@ const theme65colors = createTheme(colors, { "success": "#5f8f5f", "warning": "#8f8f5f" }); -const theme65syntax = createTheme(syntax, { +const theme67syntax = createTheme(syntax, { "comment": "#5f7f5f", "function": "#5f7f8f", "keyword": "#8f8f5f", @@ -2504,7 +2580,7 @@ const theme65syntax = createTheme(syntax, { "string": "#8f5f5f", "type": "#5f8f8f" }); -const theme65markdown = createTheme(markdown, { +const theme67markdown = createTheme(markdown, { "code": "#5f8f5f", "heading": "#8f8f5f", "quote": "#6f6f6f", @@ -2551,31 +2627,33 @@ export const themeStyles = { "mercury-light": [theme36colors, theme36syntax, theme36markdown], "monokai": [theme37colors, theme37syntax, theme37markdown], "monokai-light": [theme38colors, theme38syntax, theme38markdown], - "nightowl": [theme39colors, theme39syntax, theme39markdown], - "nightowl-light": [theme40colors, theme40syntax, theme40markdown], - "nord": [theme41colors, theme41syntax, theme41markdown], - "nord-light": [theme42colors, theme42syntax, theme42markdown], - "one-dark": [theme43colors, theme43syntax, theme43markdown], - "one-dark-light": [theme44colors, theme44syntax, theme44markdown], - "opencode": [theme45colors, theme45syntax, theme45markdown], - "opencode-light": [theme46colors, theme46syntax, theme46markdown], - "orng": [theme47colors, theme47syntax, theme47markdown], - "orng-light": [theme48colors, theme48syntax, theme48markdown], - "osaka-jade": [theme49colors, theme49syntax, theme49markdown], - "osaka-jade-light": [theme50colors, theme50syntax, theme50markdown], - "palenight": [theme51colors, theme51syntax, theme51markdown], - "palenight-light": [theme52colors, theme52syntax, theme52markdown], - "rosepine": [theme53colors, theme53syntax, theme53markdown], - "rosepine-light": [theme54colors, theme54syntax, theme54markdown], - "solarized": [theme55colors, theme55syntax, theme55markdown], - "solarized-light": [theme56colors, theme56syntax, theme56markdown], - "synthwave84": [theme57colors, theme57syntax, theme57markdown], - "synthwave84-light": [theme58colors, theme58syntax, theme58markdown], - "tokyonight": [theme59colors, theme59syntax, theme59markdown], - "tokyonight-light": [theme60colors, theme60syntax, theme60markdown], - "vercel": [theme61colors, theme61syntax, theme61markdown], - "vercel-light": [theme62colors, theme62syntax, theme62markdown], - "vesper": [theme63colors, theme63syntax, theme63markdown], - "zenburn": [theme64colors, theme64syntax, theme64markdown], - "zenburn-light": [theme65colors, theme65syntax, theme65markdown], + "neon-city-dark": [theme39colors, theme39syntax, theme39markdown], + "nightowl": [theme40colors, theme40syntax, theme40markdown], + "nightowl-light": [theme41colors, theme41syntax, theme41markdown], + "nord": [theme42colors, theme42syntax, theme42markdown], + "nord-light": [theme43colors, theme43syntax, theme43markdown], + "one-dark": [theme44colors, theme44syntax, theme44markdown], + "one-dark-light": [theme45colors, theme45syntax, theme45markdown], + "opencode": [theme46colors, theme46syntax, theme46markdown], + "opencode-light": [theme47colors, theme47syntax, theme47markdown], + "orng": [theme48colors, theme48syntax, theme48markdown], + "orng-light": [theme49colors, theme49syntax, theme49markdown], + "osaka-jade": [theme50colors, theme50syntax, theme50markdown], + "osaka-jade-light": [theme51colors, theme51syntax, theme51markdown], + "palenight": [theme52colors, theme52syntax, theme52markdown], + "palenight-light": [theme53colors, theme53syntax, theme53markdown], + "rosepine": [theme54colors, theme54syntax, theme54markdown], + "rosepine-light": [theme55colors, theme55syntax, theme55markdown], + "seti": [theme56colors, theme56syntax, theme56markdown], + "solarized": [theme57colors, theme57syntax, theme57markdown], + "solarized-light": [theme58colors, theme58syntax, theme58markdown], + "synthwave84": [theme59colors, theme59syntax, theme59markdown], + "synthwave84-light": [theme60colors, theme60syntax, theme60markdown], + "tokyonight": [theme61colors, theme61syntax, theme61markdown], + "tokyonight-light": [theme62colors, theme62syntax, theme62markdown], + "vercel": [theme63colors, theme63syntax, theme63markdown], + "vercel-light": [theme64colors, theme64syntax, theme64markdown], + "vesper": [theme65colors, theme65syntax, theme65markdown], + "zenburn": [theme66colors, theme66syntax, theme66markdown], + "zenburn-light": [theme67colors, theme67syntax, theme67markdown], } as const; From 271c0f8d2a35648d1b45056d57432590b783483c Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 22:41:30 -0700 Subject: [PATCH 21/67] clean up tabs and session info --- apps/web/scripts/browser-toolbar.mjs | 11 +++---- apps/web/scripts/new-chat-tabs.mjs | 3 +- apps/web/scripts/performance.mjs | 2 +- apps/web/scripts/repl-viewer.mjs | 6 ++-- apps/web/scripts/session-actions.mjs | 2 +- apps/web/scripts/session-tabs.mjs | 13 +++++++++ apps/web/scripts/settings-conversation.mjs | 2 +- apps/web/scripts/workspace-layout.mjs | 2 +- docs/frontend.md | 22 +++++++++----- packages/app/src/session-tab-strip.tsx | 15 +++++----- packages/app/src/session-top-bar.tsx | 10 ++----- packages/app/test/session-top-bar.test.tsx | 23 ++++++++++----- packages/ui/src/overlays.tsx | 8 ++++- packages/ui/src/workspace-tabs.stylex.ts | 15 +++++++++- packages/ui/tests/workspace-tabs.mjs | 34 ++++++++++++++++++++++ 15 files changed, 123 insertions(+), 45 deletions(-) diff --git a/apps/web/scripts/browser-toolbar.mjs b/apps/web/scripts/browser-toolbar.mjs index ad71d3e5c..b763e772e 100644 --- a/apps/web/scripts/browser-toolbar.mjs +++ b/apps/web/scripts/browser-toolbar.mjs @@ -49,11 +49,12 @@ try { await expect(switcher.getByRole('button', { pressed: true })).toHaveCount(1); await expect(switcher.getByRole('button', { name, exact: true })).toHaveAttribute('aria-pressed', 'true'); } - if (width > 600) { - await topBar.getByRole('button', { name: 'Session details', exact: true }).click(); - await expect(topBar.getByRole('button', { name: 'Hide session details' })).toHaveAttribute('aria-expanded', 'true'); - await topBar.getByRole('button', { name: 'Hide session details' }).click(); - } + await expect(topBar.getByRole('button', { name: 'Session details', exact: true })).toHaveCount(0); + await topBar.getByRole('button', { name: 'Session actions', exact: true }).click(); + await expect(page.getByRole('menuitem', { name: /^(REPL|Trace)$/ })).toHaveCount(0); + await page.getByRole('menuitem', { name: 'Session details', exact: true }).click(); + await topBar.getByRole('button', { name: 'Session actions', exact: true }).click(); + await page.getByRole('menuitem', { name: 'Hide session details', exact: true }).click(); const session = await topBar.boundingBox(); const buttons = await switcher.getByRole('button').all(); for (const button of buttons) { diff --git a/apps/web/scripts/new-chat-tabs.mjs b/apps/web/scripts/new-chat-tabs.mjs index 2fd27b4b5..457c330b6 100644 --- a/apps/web/scripts/new-chat-tabs.mjs +++ b/apps/web/scripts/new-chat-tabs.mjs @@ -109,8 +109,9 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await command('Reopen closed tab'); await ready(); assert.equal(id(), second); assert.equal(await draft().inputValue(), 'Second independent unsent task.'); checks.push('closing and reopening a draft preserves identity and text'); - await tabRow(second).getByRole('button', { name: 'Tab actions for New Chat', exact: true }).click(); + await tabRow(second).getByRole('tab').click({ button: 'right' }); assert.equal(await page.getByRole('menuitem', { name: 'Copy session link', exact: true }).count(), 0); + assert.deepEqual((await page.getByRole('menuitem').allTextContents()).slice(-3), ['Close tab', 'Close other tabs', 'Close tabs to the right']); await page.getByRole('menuitem', { name: 'Move to split right', exact: true }).click(); await eventually(async () => (await draft().count()) === 2); await page.screenshot({ path: join(directory, `${name}-split.png`) }); diff --git a/apps/web/scripts/performance.mjs b/apps/web/scripts/performance.mjs index ac2fb458d..5d1269c97 100644 --- a/apps/web/scripts/performance.mjs +++ b/apps/web/scripts/performance.mjs @@ -387,7 +387,7 @@ const frame = () => }, { description: 'settled pre-switch reading anchor' }); }; const rootAnchor = await stableAnchor(); - await page.locator(`[data-workspace-tab="${fixture.info.root_id}"]`).getByRole('button', { name: /^Tab actions for / }).click(); + await page.locator(`[data-workspace-tab="${fixture.info.root_id}"]`).getByRole('tab').click({ button: 'right' }); await page.getByRole('menuitem', { name: 'Session details', exact: true }).click(); await page.getByRole('link', { name: 'perf-child-000', exact: true }).click(); await ready(); diff --git a/apps/web/scripts/repl-viewer.mjs b/apps/web/scripts/repl-viewer.mjs index df533b7cb..e1801d019 100644 --- a/apps/web/scripts/repl-viewer.mjs +++ b/apps/web/scripts/repl-viewer.mjs @@ -60,7 +60,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await expect(page.locator('html')).toHaveAttribute('data-theme', /claude-code|light|dark/); }; const action = async (id, label) => { - await page.locator(`[data-workspace-tab="${id}"]`).getByRole('button', { name: /^Tab actions for / }).click(); + await page.locator(`[data-workspace-tab="${id}"]`).getByRole('tab').click({ button: 'right' }); await page.getByRole('menuitem', { name: label, exact: true }).click(); await page.getByRole('menu').waitFor({ state: 'hidden' }); }; @@ -142,8 +142,8 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' assert.ok(chatAnchor, 'Chat has no readable anchor'); const initialSnapshots = frames.filter(frame => frame.method === 'root.snapshot').length; const initialHistory = frames.filter(frame => frame.method === 'history.page').length; - await page.locator(`[data-workspace-tab="${root}"]`).getByRole('button', { name: /^Tab actions for / }).focus(); - await page.keyboard.press('Enter'); + await page.locator(`[data-workspace-tab="${root}"]`).getByRole('tab').focus(); + await page.keyboard.press('Shift+F10'); await page.getByRole('menuitem', { name: 'Open REPL', exact: true }).press('Enter'); const repl = leaves((await workspace()).layout)[0].selected; assert.notEqual(repl, root); diff --git a/apps/web/scripts/session-actions.mjs b/apps/web/scripts/session-actions.mjs index e7b5047d7..a1ca98d20 100644 --- a/apps/web/scripts/session-actions.mjs +++ b/apps/web/scripts/session-actions.mjs @@ -38,7 +38,7 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await page.locator('[data-whip-composer]').waitFor(); await row(other).waitFor(); // The shared dialog also stacks above Session details and returns focus. - await page.getByRole('button', { name: /^Tab actions for / }).click(); + await page.getByRole('tab', { selected: true }).click({ button: 'right' }); await page.getByRole('menuitem', { name: 'Session details', exact: true }).click(); const details = page.getByRole('dialog', { name: 'Session details', exact: true }); await details.getByRole('button', { name: 'Session actions', exact: true }).click(); diff --git a/apps/web/scripts/session-tabs.mjs b/apps/web/scripts/session-tabs.mjs index 827805b69..90a302bc6 100644 --- a/apps/web/scripts/session-tabs.mjs +++ b/apps/web/scripts/session-tabs.mjs @@ -56,6 +56,19 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await context.addInitScript(seed => { if (!sessionStorage.getItem('whip.web.tabs.v1')) sessionStorage.setItem('whip.web.tabs.v1', JSON.stringify(seed)); }, seed); await page.goto(origin + route(roots[0])); await ready(); await eventually(async () => (await page.getByRole('tab').count()) === 4, { description: 'four restored tabs' }); + assert.equal(await page.getByRole('button', { name: /^Tab actions for / }).count(), 0); + await tab(roots[1]).click({ button: 'right' }); + assert.deepEqual((await page.getByRole('menuitem').allTextContents()).slice(-3), ['Close tab', 'Close other tabs', 'Close tabs to the right']); + assert.equal(await tab(roots[0]).getAttribute('aria-selected'), 'true'); + await page.keyboard.press('Escape'); + await tab(roots[0]).focus(); + await page.keyboard.press('Shift+F10'); + await page.getByRole('menuitem', { name: 'Open trace', exact: true }).waitFor(); + await page.keyboard.press('Escape'); + await page.locator('[data-session-info-bar]').getByRole('button', { name: 'Session actions', exact: true }).click(); + assert.equal(await page.getByRole('menuitem', { name: /^(Trace|Session details|Hide session details)$/ }).count(), 0); + await page.keyboard.press('Escape'); + checks.push('tabs omit ellipsis controls; right-click and keyboard menus keep close actions last; session overflow omits Trace and details'); assert.equal(await tab(roots[0]).getAttribute('aria-selected'), 'true'); await eventually(() => frames.some(frame => frame.method === 'sessions.summaries'), { description: 'background summary query' }); assert.equal(frames.filter(frame => frame.method === 'root.snapshot').length, 1, 'Restoring labels opened extra roots'); diff --git a/apps/web/scripts/settings-conversation.mjs b/apps/web/scripts/settings-conversation.mjs index 5c5720187..65cb7ebcc 100644 --- a/apps/web/scripts/settings-conversation.mjs +++ b/apps/web/scripts/settings-conversation.mjs @@ -47,7 +47,7 @@ async function scenario(engine, mode, run) { const tab = id => page.locator(`[id="whip-workspace-tab-${encodeURIComponent(id)}"]`); const contentReads = () => httpReads.length + frames.filter(frame => frame.method === 'content.read').length; const action = async (id, label) => { - await page.locator(`[data-workspace-tab="${id}"]`).getByRole('button', { name: /^Tab actions for / }).click(); + await page.locator(`[data-workspace-tab="${id}"]`).getByRole('tab').click({ button: 'right' }); await page.getByRole('menuitem', { name: label, exact: true }).click(); await page.getByRole('menu').waitFor({ state: 'hidden' }); }; diff --git a/apps/web/scripts/workspace-layout.mjs b/apps/web/scripts/workspace-layout.mjs index af4f4bdb7..a32526b9f 100644 --- a/apps/web/scripts/workspace-layout.mjs +++ b/apps/web/scripts/workspace-layout.mjs @@ -80,7 +80,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await eventually(async () => (await workspace()).focusedPaneId === 'main', { description: 'Back focuses original duplicate URL' }); await page.goForward(); await tab(root).click(); - await page.locator(`[data-workspace-tab="${duplicate}"]`).getByRole('button', { name: /^Tab actions for / }).click(); + await page.locator(`[data-workspace-tab="${duplicate}"]`).getByRole('tab').click({ button: 'right' }); await page.getByRole('menuitem', { name: 'Session details', exact: true }).click(); await page.getByRole('link', { name: 'perf-child-000', exact: true }).click(); await panel(duplicate).getByLabel('Message this agent', { exact: true }).waitFor(); diff --git a/docs/frontend.md b/docs/frontend.md index ddcaa6c88..ec9b05cfa 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -2135,8 +2135,13 @@ Tab creation, selection, reorder, close, and reopen are local navigation actions Desktop tabs retain their original rounded upper corners and curved lower shoulders in the 48px strip; selected tabs join the content canvas. Theme tokens -also style the matching contoured drag preview. Tabs keep readable widths in a horizontal scroller; the picker handles -overflow and secondary actions. On phones, use the current-session selector and +also style the matching contoured drag preview. Tabs keep 144–224px widths in a +horizontal scroller without inline ellipsis buttons. Titles clip through a subtle +16px inline-end fade instead of a text ellipsis, including in drag previews; +full labels remain available to assistive technology and in tooltips. The fade +reverses in RTL and is disabled for forced colors and print. Right-click or Shift+F10 +opens tab actions, with the three close actions grouped last; the picker retains +explicit action menus for touch and overflow. On phones, use the current-session selector and searchable sheet. Preserve browser Back/Forward, modified link clicks, keyboard activation, and explicit touch/menu alternatives to dragging. Do not hijack the browser's new-tab or close-tab shortcuts. @@ -2196,8 +2201,8 @@ pinned header only after scrolling, with a reduced-motion-aware opacity transiti Only directory groups collapse; there are no host headings. Each pane's tab strip sits above the shared [`SessionTopBar`](../packages/app/src/session-top-bar.tsx): host/project, selected agent, current activity and scoped actions. Chat, REPL and trace/span views use this same component, including loading and unavailable states. It owns the -fixed-position Chat / REPL / Trace single-selection view controls and a separate -Details toggle. Session view choices and the span viewer's Panes and Overview/Raw +fixed-position Chat / REPL / Trace single-selection view controls and a Session +details toggle in the overflow menu. Session view choices and the span viewer's Panes and Overview/Raw controls share the UI `ToggleGroup`: compact 2px spacing, a quiet secondary fill for selected choices, and transparent ghost buttons when inactive. Panes enables multiple selection; session views and detail mode retain exactly one selection. @@ -2208,8 +2213,9 @@ selected agent and inspector state; it never opens or selects another tab. The route binding commits the mode after navigation and restores it on Back/Forward. Explicit tab-menu opening still creates a fresh REPL/Trace. View identity, reading positions and inspector state remain owned by the workspace. Details reflects the inspector's open state, -independently of the selected view. The overflow menu uses the same callbacks; -callers provide identity, activity and callbacks +independently of the selected view. The overflow menu includes Session details +without a standalone icon, and omits REPL and Trace, which retain their dedicated +view controls; menu entries use the same callbacks. Callers provide identity, activity and callbacks rather than assembling their own top bars. Full host/path identity is available on focus through a tooltip. Agent selection opens the existing paginated inspector; child views can return to Root. REPL keeps only language, loaded-cell count and @@ -2218,8 +2224,8 @@ history help in its local toolbar. New Chat shows its chosen host/project and identity chrome; detailed errors remain in their existing notices. Narrow panes shorten the identity trail, keep an accessible activity indicator, -and move Details into the menu while retaining the three view controls. The bar shares existing session action -and inspector owners; it adds no subscriptions, context audits or polling. Models +and retain the three view controls; Details stays in the menu at every width. +The bar shares existing session action and inspector owners; it adds no subscriptions, context audits or polling. Models and permissions stay beside the composer, along with child activity and requests. Session details also opens from the tab menu or command palette. diff --git a/packages/app/src/session-tab-strip.tsx b/packages/app/src/session-tab-strip.tsx index 27be55305..96405d633 100644 --- a/packages/app/src/session-tab-strip.tsx +++ b/packages/app/src/session-tab-strip.tsx @@ -211,14 +211,15 @@ export function SessionTabStrip({ compact, onManageHosts, utilities, children, n if (!isSessionTab(tab)) return [ ...(tab.kind === 'browser' ? [{ id: 'browser-duplicate', label: 'Duplicate Browser tab', disabled: !runtime.platform.browser || !runtime.tabs.canOpenBrowser(), onSelect: () => { void openBrowserTab(runtime, navigate, { url: tab.url, environmentId: tab.environmentId, paneId: pane.id }); } }] : []), ...(tab.kind === 'terminal' ? [{ id: 'terminal-new', label: 'New terminal here', onSelect: () => void openTerminalTab(runtime, navigate, { runtimeId: tab.runtimeId, cwd: tab.cwd, paneId: pane.id }) }] : []), - { id: 'close', label: 'Close tab', onSelect: () => close([tab.id], true) }, - { id: 'others', label: 'Close other tabs', disabled: pane.tabs.length < 2, onSelect: () => close(pane.tabs.filter(item => item.id !== tab.id).map(item => item.id), true) }, - { id: 'right', label: 'Close tabs to the right', disabled: index === pane.tabs.length - 1, onSelect: () => close(pane.tabs.slice(index + 1).map(item => item.id), true) }, ...panes.filter(p => p.id !== pane.id).map(p => ({ id: `move-${p.id}`, label: `Move to pane ${panes.indexOf(p) + 1}`, onSelect: () => transfer({ viewId: tab.id, paneId: p.id }) })), { id: 'split-right', label: 'Move to split right', disabled: pane.tabs.length < 2 || !canSplit(pane.id, 'right'), onSelect: () => transfer({ viewId: tab.id, paneId: pane.id, edge: 'right' }) }, { id: 'split-down', label: 'Move to split below', disabled: pane.tabs.length < 2 || !canSplit(pane.id, 'bottom'), onSelect: () => transfer({ viewId: tab.id, paneId: pane.id, edge: 'bottom' }) }, { id: 'left', label: 'Move left', disabled: index <= 0, onSelect: () => runtime.tabs.move(tab.id, -1) }, { id: 'move-right', label: 'Move right', disabled: index >= pane.tabs.length - 1, onSelect: () => runtime.tabs.move(tab.id, 1) }, + { id: 'close-separator', separator: true, label: '' }, + { id: 'close', label: 'Close tab', onSelect: () => close([tab.id], true) }, + { id: 'others', label: 'Close other tabs', disabled: pane.tabs.length < 2, onSelect: () => close(pane.tabs.filter(item => item.id !== tab.id).map(item => item.id), true) }, + { id: 'right', label: 'Close tabs to the right', disabled: index === pane.tabs.length - 1, onSelect: () => close(pane.tabs.slice(index + 1).map(item => item.id), true) }, ]; const href = new URL(`/h/${encodeURIComponent(tab.runtimeId)}/s/${encodeURIComponent(tab.rootId)}`, 'https://whip.invalid'); for (const [key, value] of Object.entries(sessionSearch(tab))) if (value) href.searchParams.set(key, value); @@ -229,9 +230,6 @@ export function SessionTabStrip({ compact, onManageHosts, utilities, children, n } })), { id: 'details', label: 'Session details', onSelect: () => { setPicker(false); void navigate({ to: '/h/$runtimeId/s/$rootId', params: { runtimeId: tab.runtimeId, rootId: tab.rootId }, search: { ...sessionSearch(tab), panel: 'agents' }, state: { whipViewId: tab.id } }); } }, { id: 'terminal', label: 'Open terminal here', onSelect: () => { setPicker(false); void openTerminalTab(runtime, navigate, { runtimeId: tab.runtimeId, cwd: item(tab)?.cwd, rootId: tab.rootId, paneId: pane.id }); } }, - { id: 'close', label: 'Close tab', onSelect: () => close([tab.id], true) }, - { id: 'others', label: 'Close other tabs', disabled: pane.tabs.length < 2, onSelect: () => close(pane.tabs.filter(item => item.id !== tab.id).map(item => item.id), true) }, - { id: 'right', label: 'Close tabs to the right', disabled: index === pane.tabs.length - 1, onSelect: () => close(pane.tabs.slice(index + 1).map(item => item.id), true) }, { id: 'separator', separator: true, label: '' }, { id: 'split-right', label: 'Split right', disabled: !canSplit(pane.id, 'right') || tabs.length >= 32, onSelect: () => split(tab, 'right') }, { id: 'split-down', label: 'Split down', disabled: !canSplit(pane.id, 'bottom') || tabs.length >= 32, onSelect: () => split(tab, 'bottom') }, @@ -240,6 +238,10 @@ export function SessionTabStrip({ compact, onManageHosts, utilities, children, n { id: 'left', label: 'Move left', disabled: index <= 0, onSelect: () => runtime.tabs.move(tab.id, -1) }, { id: 'move-right', label: 'Move right', disabled: index >= pane.tabs.length - 1, onSelect: () => runtime.tabs.move(tab.id, 1) }, { id: 'link', label: 'Copy session link', onSelect: () => void runtime.platform.copy(runtime.platform.sessionLink ? runtime.platform.sessionLink(href.pathname + href.search, runtime.connections.host(tab.runtimeId)?.profile) : new URL(href.pathname + href.search, window.location.href).href).catch(error => runtime.reportWorkspace(error)) }, + { id: 'close-separator', separator: true, label: '' }, + { id: 'close', label: 'Close tab', onSelect: () => close([tab.id], true) }, + { id: 'others', label: 'Close other tabs', disabled: pane.tabs.length < 2, onSelect: () => close(pane.tabs.filter(item => item.id !== tab.id).map(item => item.id), true) }, + { id: 'right', label: 'Close tabs to the right', disabled: index === pane.tabs.length - 1, onSelect: () => close(pane.tabs.slice(index + 1).map(item => item.id), true) }, ]; }; useImperativeHandle(ref, () => ({ @@ -265,7 +267,6 @@ export function SessionTabStrip({ compact, onManageHosts, utilities, children, n items={pane.tabs.map(tab => ({ value: tab.id, label: title(tab), accessibleLabel: `${title(tab)} · ${hostName(tab)}${viewSuffix(tab.kind)}${panes.length > 1 ? ` · Pane ${panes.indexOf(pane) + 1}` : ''}${isSessionTab(tab) && tab.location.agent ? ` · Agent ${tab.location.agent}` : ''} · ${kindLabel(tab)}${hasDraft(tab) ? ' · Unsent draft' : ''}`, render: <Link {...tabDestination(tab)} />, status: icon(tab), metadata: <>{viewSuffix(tab.kind).replace(' · ', '')}{hasDraft(tab) && <Pencil aria-label="Unsent draft" size={10}/>}</>, tooltip: `${title(tab)} · ${hostName(tab)}${viewSuffix(tab.kind)}${project(tab) ? ` · ${project(tab)}` : ''}`, - menu: <Menu trigger={<IconButton variant="ghost" label={`Tab actions for ${title(tab)}`}><MoreHorizontal size={13}/></IconButton>} items={actions(tab)} />, wrap: (element: ReactElement) => <ContextMenu items={actions(tab)}>{element}</ContextMenu>, }))}/>; const visiblePanes = matched ? panes.filter(p => !(compact || small) || p.id === workspace.focusedPaneId) : []; diff --git a/packages/app/src/session-top-bar.tsx b/packages/app/src/session-top-bar.tsx index ac43ab6e4..5b275b4a1 100644 --- a/packages/app/src/session-top-bar.tsx +++ b/packages/app/src/session-top-bar.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from 'react'; import { Button, IconButton, Menu, ToggleGroup, Tooltip, type MenuItem } from '@whip/ui'; -import { ChevronDown, MoreHorizontal, PanelRight } from 'lucide-react'; +import { ChevronDown, MoreHorizontal } from 'lucide-react'; import * as stylex from '@stylexjs/stylex'; import { colors, scale, surface, typography } from '@whip/ui/tokens.stylex'; @@ -33,7 +33,7 @@ export function SessionTopBar({ host, cwd, agentName, kind, activity, onAgents, ]; const detailsLabel = detailsOpen ? 'Hide session details' : 'Session details'; const menu: MenuItem[] = kind === 'new' ? [] : [ - ...views.filter(view => view.value !== kind && view.onSelect).map(({ value, label, onSelect }) => ({ id: value, label, onSelect })), + ...(kind !== 'chat' && onChat ? [{ id: 'chat', label: 'Chat', onSelect: onChat }] : []), ...(onDetails ? [{ id: 'details', label: detailsLabel, onSelect: onDetails }] : []), ...(onRoot ? [{ id: 'root', label: 'Root conversation', onSelect: onRoot }] : []), ...actions, @@ -55,10 +55,6 @@ export function SessionTopBar({ host, cwd, agentName, kind, activity, onAgents, items={views.map(view => ({ value: view.value, label: view.label, disabled: view.value !== kind && !view.onSelect }))} onValueChange={([next]) => { if (next && next !== kind) views.find(view => view.value === next)?.onSelect?.(); }} xstyle={styles.views} />} - {kind !== 'new' && onDetails && <span {...stylex.props(styles.secondaryAction)}> - <IconButton variant="ghost" size="sm" label={detailsLabel} aria-expanded={detailsOpen} - xstyle={detailsOpen && styles.detailsActive} onClick={onDetails}><PanelRight size={16} /></IconButton> - </span>} {!!menu.length && <Menu onOpenChange={onPrepare} trigger={<IconButton variant="ghost" size="sm" label="Session actions"><MoreHorizontal size={16} /></IconButton>} items={menu} />} </div> </div> @@ -75,7 +71,5 @@ const styles = stylex.create({ truncate: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 }, activity: { display: 'flex', alignItems: 'center', flex: { default: '1 1 0', '@container (max-width: 600px)': '0 0 auto' }, marginInlineStart: 'auto', minWidth: 0, justifyContent: 'flex-end', paddingInline: scale.space2 }, actions: { display: 'flex', alignItems: 'center', flexShrink: 0, gap: scale.space1 }, - secondaryAction: { display: { default: 'inline-flex', '@container (max-width: 600px)': 'none' } }, views: { marginInlineEnd: scale.space1 }, - detailsActive: { backgroundColor: colors.hover, borderColor: surface.quietBorder }, }); diff --git a/packages/app/test/session-top-bar.test.tsx b/packages/app/test/session-top-bar.test.tsx index ff403511c..511ea2cf4 100644 --- a/packages/app/test/session-top-bar.test.tsx +++ b/packages/app/test/session-top-bar.test.tsx @@ -7,14 +7,16 @@ import type { SessionViewSnapshot } from '@whip/sdk/state'; import { SessionTopBar } from '../src/session-top-bar'; import { activityStatus, CurrentActivity } from '../src/chat-activity'; -it('keeps full host/path identity accessible and opens scoped actions', () => { +it('keeps full host/path identity accessible and opens scoped actions', async () => { const onRepl = vi.fn(), onAgents = vi.fn(), onDetails = vi.fn(); render(<ThemeProvider><UIProvider><SessionTopBar host="Remote" cwd="/workspace/whip" agentName="reviewer" kind="chat" onRepl={onRepl} onAgents={onAgents} onDetails={onDetails} /></UIProvider></ThemeProvider>); expect(screen.getByLabelText('Remote / /workspace/whip')).toBeDefined(); fireEvent.click(screen.getByRole('button', { name: 'REPL' })); fireEvent.click(screen.getByRole('button', { name: 'Agent: reviewer' })); - fireEvent.click(screen.getByRole('button', { name: 'Session details' })); + expect(screen.queryByRole('button', { name: 'Session details' })).toBeNull(); + fireEvent.click(screen.getByRole('button', { name: 'Session actions' })); + fireEvent.click(await screen.findByRole('menuitem', { name: 'Session details' })); expect(onRepl).toHaveBeenCalledOnce(); expect(onAgents).toHaveBeenCalledOnce(); expect(onDetails).toHaveBeenCalledOnce(); }); @@ -29,7 +31,6 @@ it.each(['chat', 'repl', 'trace'] as const)('uses the same top bar and action de { label: 'Chat', enabled: kind !== 'chat', callback: onChat }, { label: 'REPL', enabled: kind !== 'repl', callback: onRepl }, { label: 'Trace', enabled: kind !== 'trace', callback: onTrace }, - { label: 'Session details', enabled: true, callback: onDetails }, ]; for (const control of controls) { if (control.enabled) { @@ -45,7 +46,7 @@ it.each(['chat', 'repl', 'trace'] as const)('uses the same top bar and action de for (const control of controls) { fireEvent.click(screen.getByRole('button', { name: 'Session actions' })); await screen.findByRole('menu'); - if (control.enabled) { + if (control.enabled && control.label === 'Chat') { fireEvent.click(screen.getByRole('menuitem', { name: control.label })); expect(control.callback).toHaveBeenCalledTimes(2); } else { @@ -54,6 +55,10 @@ it.each(['chat', 'repl', 'trace'] as const)('uses the same top bar and action de } } fireEvent.click(screen.getByRole('button', { name: 'Session actions' })); + fireEvent.click(await screen.findByRole('menuitem', { name: 'Session details' })); + expect(onDetails).toHaveBeenCalledOnce(); + expect(screen.queryByRole('button', { name: 'Session details' })).toBeNull(); + fireEvent.click(screen.getByRole('button', { name: 'Session actions' })); fireEvent.click(await screen.findByRole('menuitem', { name: 'Root conversation' })); expect(onRoot).toHaveBeenCalledOnce(); fireEvent.click(screen.getByRole('button', { name: 'Session actions' })); @@ -83,9 +88,13 @@ it('switches views with the keyboard, keeps exactly one selected, and toggles de await user.click(group.getByRole('button', { name: 'Chat' })); expect(group.getAllByRole('button', { pressed: true })).toHaveLength(1); expect(group.getByRole('button', { name: 'Chat', pressed: true })).toBeDefined(); - await user.click(screen.getByRole('button', { name: 'Session details', expanded: false })); - await user.click(screen.getByRole('button', { name: 'Hide session details', expanded: true })); - expect(screen.getByRole('button', { name: 'Session details', expanded: false })).toBeDefined(); + await user.click(screen.getByRole('button', { name: 'Session actions' })); + await user.click(await screen.findByRole('menuitem', { name: 'Session details' })); + await user.click(screen.getByRole('button', { name: 'Session actions' })); + await user.click(await screen.findByRole('menuitem', { name: 'Hide session details' })); + await user.click(screen.getByRole('button', { name: 'Session actions' })); + expect(await screen.findByRole('menuitem', { name: 'Session details' })).toBeDefined(); + await user.keyboard('{Escape}'); expect(group.getByRole('button', { name: 'Chat', pressed: true })).toBeDefined(); }); diff --git a/packages/ui/src/overlays.tsx b/packages/ui/src/overlays.tsx index 2866e25fb..34ed63726 100644 --- a/packages/ui/src/overlays.tsx +++ b/packages/ui/src/overlays.tsx @@ -46,7 +46,13 @@ export function Menu({trigger, items, align = 'end', onOpenChange}: {trigger: Re } export function ContextMenu({children, items, onOpenChange}: {children: ReactElement; items: readonly MenuItem[]; onOpenChange?: (open: boolean) => void}) { const overlay = useNativeOverlay(undefined, onOpenChange); - return <BaseContextMenu.Root {...overlay}><BaseContextMenu.Trigger render={children}/><BaseContextMenu.Portal><BaseContextMenu.Positioner {...stylex.props(styles.positioner)}><BaseContextMenu.Popup {...stylex.props(styles.popup)}><MenuItems items={items}/></BaseContextMenu.Popup></BaseContextMenu.Positioner></BaseContextMenu.Portal></BaseContextMenu.Root>; + return <BaseContextMenu.Root {...overlay}><BaseContextMenu.Trigger render={children} onKeyDown={event => { + if (event.defaultPrevented || !(event.key === 'ContextMenu' || (event.shiftKey && event.key === 'F10'))) return; + event.preventDefault(); + // Firefox on macOS does not synthesize contextmenu for these keyboard shortcuts. + const rect = event.currentTarget.getBoundingClientRect(); + event.currentTarget.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true, clientX: rect.left, clientY: rect.bottom })); + }}/><BaseContextMenu.Portal><BaseContextMenu.Positioner {...stylex.props(styles.positioner)}><BaseContextMenu.Popup {...stylex.props(styles.popup)}><MenuItems items={items}/></BaseContextMenu.Popup></BaseContextMenu.Positioner></BaseContextMenu.Portal></BaseContextMenu.Root>; } export function Popover({trigger, title, children, open, onOpenChange, side, align, xstyle}: {trigger: ReactElement; title?: ReactNode; children: ReactNode; open?: boolean; onOpenChange?: (value: boolean) => void; side?: BasePopover.Positioner.Props['side']; align?: BasePopover.Positioner.Props['align']} & Styled) { const overlay = useNativeOverlay(open, onOpenChange); diff --git a/packages/ui/src/workspace-tabs.stylex.ts b/packages/ui/src/workspace-tabs.stylex.ts index 6f0ae98a7..5a5f82cf6 100644 --- a/packages/ui/src/workspace-tabs.stylex.ts +++ b/packages/ui/src/workspace-tabs.stylex.ts @@ -18,7 +18,20 @@ export const styles = stylex.create({ tab: { display: 'flex', alignItems: 'center', gap: 8, flex: '1 1 auto', minWidth: 0, height: '100%', paddingInlineStart: scale.space3, paddingInlineEnd: scale.space1, borderWidth: 0, borderStyle: 'none', backgroundColor: 'transparent', color: surface.secondaryText, fontFamily: typography.sans, fontSize: typography.size13, fontWeight: 500, lineHeight: '1.5385', textDecoration: 'none', textAlign: 'start', whiteSpace: 'nowrap', cursor: 'pointer', userSelect: 'none', borderStartStartRadius: scale.radiusDialog, borderStartEndRadius: scale.radiusDialog, outline: { default: 'none', ':focus-visible': `1px solid ${surface.secondaryText}` }, outlineOffset: -2 }, activeText: { color: colors.foreground }, status: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 14px', width: 14, height: 14 }, - title: { flex: '1 1 auto', minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }, + title: { + flex: '1 1 auto', minWidth: 0, overflow: 'hidden', paddingInlineEnd: 16, + // End padding keeps fitting titles out of the fade; overflowing text clips through it. + maskImage: { + default: 'linear-gradient(to right, black calc(100% - 16px), transparent)', + ':is([dir="rtl"] *)': 'linear-gradient(to left, black calc(100% - 16px), transparent)', + '@media (forced-colors: active), (update: none)': 'none', + }, + WebkitMaskImage: { + default: 'linear-gradient(to right, black calc(100% - 16px), transparent)', + ':is([dir="rtl"] *)': 'linear-gradient(to left, black calc(100% - 16px), transparent)', + '@media (forced-colors: active), (update: none)': 'none', + }, + }, metadata: { flex: '0 1 auto', minWidth: 0, maxWidth: 88, overflow: 'hidden', textOverflow: 'ellipsis', color: surface.secondaryText, fontSize: typography.size11 }, menu: { display: 'flex', alignItems: 'center', flexShrink: 0, opacity: { default: 0, [stylex.when.ancestor(':hover', tabMarker)]: 1, [stylex.when.ancestor(':focus-within', tabMarker)]: 1, [scale.touch]: 1 } }, menuVisible: { opacity: 1 }, diff --git a/packages/ui/tests/workspace-tabs.mjs b/packages/ui/tests/workspace-tabs.mjs index c344df74d..a143cbbef 100644 --- a/packages/ui/tests/workspace-tabs.mjs +++ b/packages/ui/tests/workspace-tabs.mjs @@ -43,6 +43,33 @@ try { const visit = async (params = '') => { await page.goto(`${origin}/${params}`); await expect(page.getByRole('tab')).toHaveCount(params.includes('many') ? 32 : 4); }; const tab = value => page.locator(`[role="tab"][id="whip-workspace-tab-${value}"]`); const selected = value => expect(page.getByLabel('Active session', { exact: true })).toHaveText(value); + // Fade only title text, retain full names, and protect short labels from the fade. + await visit(); + const title = tab('gamma').locator(':scope > span').nth(1); + const titleStyle = () => title.evaluate(element => ({ + mask: getComputedStyle(element).maskImage, overflow: getComputedStyle(element).textOverflow, + clipped: element.scrollWidth > element.clientWidth, + })); + assert.equal((await titleStyle()).overflow, 'clip'); + assert.match((await titleStyle()).mask, /to right/); + assert.equal((await titleStyle()).clipped, true); + await expect(tab('gamma')).toHaveAccessibleName(/A long translated session name that remains readable and accessible/); + assert.equal(await tab('gamma').evaluate(element => getComputedStyle(element.firstElementChild).maskImage), 'none'); + await title.evaluate(element => { element.textContent = 'Short'; }); + assert.ok(await title.evaluate(element => { + const range = document.createRange(); range.selectNodeContents(element); + return range.getBoundingClientRect().right <= element.getBoundingClientRect().right - 16; + }), 'A fitting title should remain fully opaque'); + await page.emulateMedia({ forcedColors: 'active' }); + assert.equal((await titleStyle()).mask, 'none'); + await page.emulateMedia({ forcedColors: 'none', media: 'print' }); + assert.equal((await titleStyle()).mask, 'none'); + await page.emulateMedia({ media: 'screen' }); + await visit('?rtl'); + assert.match((await titleStyle()).mask, /to left/); + await page.emulateMedia({ forcedColors: 'active' }); + assert.equal((await titleStyle()).mask, 'none'); + await page.emulateMedia({ forcedColors: 'none' }); // A crowded strip must spend its label space on the title, not host metadata. await page.setViewportSize({ width: 800, height: 600 }); await visit('?many'); @@ -96,6 +123,13 @@ try { await tab('gamma').click({ modifiers: [process.platform === 'darwin' ? 'Meta' : 'Control'] }); await (await popup).close(); await selected('alpha'); await expect(page.getByLabel('Navigation count', { exact: true })).toHaveText('1'); + for (const shortcut of ['Shift+F10', 'ContextMenu']) { + await tab('gamma').focus(); + await page.keyboard.press(shortcut); + await expect(page.getByRole('menuitem', { name: 'Move left', exact: true })).toBeVisible(); + await page.keyboard.press('Escape'); + await selected('alpha'); + } await tab('gamma').click({ button: 'right' }); await page.getByRole('menuitem', { name: 'Move left', exact: true }).click(); await expect(page.getByLabel('Reordered sessions', { exact: true })).toHaveText('gamma,alpha,delta'); From db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:32:41 -0700 Subject: [PATCH 22/67] fix(deps): patch brace-expansion audit findings --- package-lock.json | 66 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86ebb693c..2caae1479 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2249,9 +2249,9 @@ "license": "MIT" }, "node_modules/@electron/asar/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -2425,9 +2425,9 @@ "license": "MIT" }, "node_modules/@electron/node-gyp/node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { @@ -2670,9 +2670,9 @@ "license": "MIT" }, "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { @@ -5175,9 +5175,9 @@ "license": "MIT" }, "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -10849,9 +10849,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -11018,9 +11018,9 @@ "license": "MIT" }, "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { @@ -12406,9 +12406,9 @@ "license": "MIT" }, "node_modules/dir-compare/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -15888,9 +15888,9 @@ "license": "MIT" }, "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -16752,9 +16752,9 @@ "license": "MIT" }, "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -22969,9 +22969,9 @@ "license": "MIT" }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "dependencies": { @@ -24356,9 +24356,9 @@ "license": "MIT" }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "devOptional": true, "license": "MIT", "dependencies": { From f1e3e456ef52d7f34d6564113eb979c859c51712 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:35:26 -0700 Subject: [PATCH 23/67] ci: run full checks for backend reorganization stacks --- .github/workflows/ci.yml | 2 +- .github/workflows/security.yml | 2 +- docs/backend-reorganization-plan.md | 652 ++++++++++++++++++++++++++++ 3 files changed, 654 insertions(+), 2 deletions(-) create mode 100644 docs/backend-reorganization-plan.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00de9cd41..c9e0ad4b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ name: ci on: workflow_call: pull_request: - branches: [main, development] + branches: [main, development, 'codex/backend-reorg-*'] push: branches: [main, development] diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index bc64804d4..75ef0e5b8 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -4,7 +4,7 @@ name: security on: workflow_call: pull_request: - branches: [main, development] + branches: [main, development, 'codex/backend-reorg-*'] push: branches: [main, development] schedule: diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md new file mode 100644 index 000000000..4d8b8cb32 --- /dev/null +++ b/docs/backend-reorganization-plan.md @@ -0,0 +1,652 @@ +# Backend reorganization with a frozen client contract + +Status: implementation authorized; preparing an unmerged PR stack for review. + +Execution instruction, September 29: the user authorized end-to-end overnight +execution with all work ready for morning review. For this execution, prepare +successive PRs without waiting for human review between steps. Keep changes +sequential and independently verified, preserve the compatibility constraints, +and leave every PR unmerged. The checkpoints below are evidence and eventual +merge checkpoints; human review occurs after the stack is prepared. + +Research date: September 29, 2026 (America/Los_Angeles). +Starting development revision: [`271c0f8d2a35648d1b45056d57432590b783483c`](https://github.com/context-labs/whip/commit/271c0f8d2a35648d1b45056d57432590b783483c), +verified against GitHub and the clean local checkout. Some linked CI timestamps +are September 30 in UTC. + +## 1. Purpose and definition of success + +Make the existing backend easier to understand, change, and test without +changing the product it implements. A developer should be able to identify +which component owns a responsibility, what it depends on, who creates and +closes its resources, and where to make a change without following unrelated +code through the daemon. + +The problem is accumulated coupling and unclear responsibility. The previous +redesign combined that problem with new protocols, storage, execution semantics, +and client adoption. Its scope made regressions hard to detect and attribution +harder. This effort deliberately separates structural improvement from those +product and protocol decisions. + +The expected improvements are all four of the following: + +| Improvement | What this effort can accomplish | Boundary it must respect | +| --- | --- | --- | +| Package boundaries | Move coherent implementations behind small package APIs; separate native client code from server implementation. | Existing protocol and storage types can remain shared. Package purity does not justify conversion layers. | +| Resource ownership | Give live resources explicit constructors, borrowers, and shutdown owners. | Creation, cancellation, sharing, and teardown must happen at the same points in execution. | +| Dependency direction | Keep domain services independent of daemon orchestration; keep clients from importing the runtime implementation. | Existing representation dependencies remain when removing them would require a new model or schema. | +| Smaller responsibilities | Separate provider setup, MCP host configuration, startup wiring, persistence operations, and selected actor helpers. | Extract existing work without changing scheduling, transaction boundaries, or event publication. | + +Success is a useful improvement after each merged PR. Completing an idealized +directory tree, reaching a package-count target, or finishing every possible +extraction is not required. A smaller daemon with understandable remaining +coupling is a valid outcome. + +## 2. Decisions and hard constraints + +These apply to every PR, including an apparently mechanical move. + +1. **Freeze the SDK and all observable client behavior.** Preserve SDK source, + exports, request and response shapes, event shapes, omitted/null/empty values, + validation, error codes/kinds/messages, capability negotiation, identifiers, + sequence numbers, ordering, command acceptance, deduplication, cancellation, + reconnect, replay, snapshot fallback, and restart recovery. Preserve the + current protocol version, **6.9**. No frontend migration is part of this work. +2. **Use one implementation and the existing representations.** No new protocol, + replacement runtime, alternate execution path, dual writes, compatibility + mode, or old-to-new translation layer. Services may accept and return the + existing `protocol` and `session` types directly. Existing provider encoders + and client projections remain; this does not mean deleting legitimate + conversions that already exist. +3. **Preserve database schema and persisted-data compatibility.** No schema + revision, table redesign, migration rewrite, reset, import, changed config + format, runtime-home relocation, content-handle format, checkpoint format, + or changed acceptance/rejection of older stores. Preserve transaction and + recovery behavior, including opening data written by the previous binary + and rolling back to that binary after the candidate has written data. + The recorded development schema is version **21**, with identity + `whip-recursive-runtime-v21`; preserve its existing upgrade paths too. +4. **Preserve runtime features and semantics.** REPL APIs and guidance, both + execution engines, scratch/checkpoint behavior, retained children, + inheritance, mail, reporting, budgets, permissions, tools, MCP, browser and + terminal ownership, model routing, compaction, provider retries and request + encoding, tracing, usage/cost accounting, and exports remain intact. + Prompts and defaults are behavior too. +5. **Keep behavior changes separate.** Discovered bugs, dependency upgrades, + performance optimizations, feature removals, and new policies get separately + proposed PRs. A cleanup PR cannot quietly fix a bug or update an expected + result to fit a changed implementation. +6. **Start from current development.** Do not continue or merge the abandoned + redesign stack. Recheck development before implementation and record any + intervening commits. Review those deltas explicitly before updating the + baseline; never silently redefine compatibility as whatever now passes. +7. **Work sequentially in reviewed stacks.** One PR under active implementation + or review at a time; human approval before starting the next. Reviewed PRs + remain stacked until the checkpoint for their group, then merge in dependency + order. No parallel stream of speculative follow-up PRs. Each step must work + independently and preserve all existing gates. +8. **Allow mechanical Go client moves.** Moving the existing Go client into a + dedicated package and updating CLI/TUI/ACP imports is in scope. Preserve its + APIs and behavior apart from internal Go import paths. The TypeScript SDK + remains untouched. + +These constraints and the checkpoint merge cadence are confirmed by the user. +There are no remaining planning preference questions. The overnight execution +instruction above supersedes waiting for human approval between implementation +steps; it does not authorize merging the resulting PRs. + +Type aliases can preserve Go type identity during a package move; they do not +translate values. Use them only where they simplify the move, identify which +callers still need them, and remove unnecessary internal aliases as callers +move. Do not create a permanent forwarding service API to simulate two +architectures. Go's [type-alias guidance](https://go.dev/blog/alias-names) +supports incremental package moves without introducing distinct types. + +## 3. What the repository research established + +### Starting point and previous work + +Development already includes [PR #196](https://github.com/context-labs/whip/pull/196), +which improved session-state ownership and retained protocol 6.9. Preserve that +work. There is no reason to undo it to pursue this plan. + +The new domain/schema/protocol work in [PR #199](https://github.com/context-labs/whip/pull/199), +recursive semantics in [PR #202](https://github.com/context-labs/whip/pull/202), +renderer adoption in [PR #265](https://github.com/context-labs/whip/pull/265), and +REPL repair in [PR #296](https://github.com/context-labs/whip/pull/296) remain +unmerged. They demonstrate why that stack is unsuitable as this effort's base. +Its ownership observations and regression scenarios may be useful references; +its replacement types, lifecycle policies, and assertions are not the contract. +Do not cherry-pick its repairs without independently showing relevance to +development. + +This plan supersedes [backend-redesign-plan.md](backend-redesign-plan.md) **as +the proposal for this reorganization**. The earlier plan remains historical +context, not an additional set of requirements. Current implementation guides +remain authoritative about implemented behavior; a stale reference in a guide +must be checked against code. For example, some architecture prose still calls +the protocol v4, while `internal/protocol/types.go` declares 6.9. + +### Current ownership and coupling + +The package inventory found 44 Go packages. On the active macOS build, +`internal/daemon` has 82 production Go files and 123 test files; +`internal/session` has 55 and 67 respectively. These are orientation figures, +not targets. Go language-server analysis found 376 references to `Store` +across 91 files and 73 to `ProviderService` across 21 files, including tests. +Refresh references for the exact revision and build tags before each move. + +| Area | Current evidence | Consequence for the plan | +| --- | --- | --- | +| Daemon | `daemon.go`, `session.go`, `server.go`, provider services, clients, host handlers, recursive runtime, and transport-facing code share a package. | Separate coherent outer responsibilities before touching actor scheduling. | +| Provider setup | `ProviderService` owns login flows, credentials/catalog operations, and configuration, but also MCP import methods and lazy brand-icon state. | Separate the unrelated MCP host responsibility before moving provider implementation. | +| Shared configuration | `UpdateConfiguration` changes provider defaults and host settings in one versioned update, sometimes under the provider provisioning lock. Command handling and model admission call private provider helpers. | Preserve atomic updates and lock order; prepare narrow operation boundaries before extracting the package. | +| Persistence | `session.Store` opens SQLite and also constructs `capability.Workspaces` and `ProcessManager`; `Store.Close` closes processes before SQLite. | Resource ownership can improve without changing SQL. Process and workspace moves must be separate. | +| Workspace authority | `session/permission.go` opens/canonicalizes a workspace inside delegation's transaction; root authority setup has a different ordering. | Preserve both orderings. Do not move validation across a transaction to make a package appear pure. | +| Root and child execution | `AgentSession.RunTurn` already serves both. `RecursiveRuntime` owns the live tree; root scheduling and child scheduling/commit paths differ. | Extract shared implementation only where it is already shared. No new universal scheduler or session record. | +| Native clients | TUI and ACP import `daemon` for `Client`, `RootClient`, aliases, and connection helpers. | A dedicated Go client package offers a real dependency improvement without changing the wire contract. | +| Protocol types | `internal/protocol` imports `session`, `config`, `llm`, `capability`, `mcp`, and other existing packages. | It is not a dependency-free leaf. Moving protocol-consuming code into those packages can create cycles. | +| Transport | `internal/protocoltransport` already owns Unix/WebSocket framing. `serverConn` owns delivery queues and subscriptions. | Reuse framing. Keep queue, reconnect, and publication mechanics in place during initial service extractions. | +| Tracing | `daemon/spans.go` records causal relationships at runtime; `session/span.go` and OTLP code persist/query/export them. | Keep recording at the same execution points. Moving tracing into a delayed observer would change behavior. | +| Startup | `cmd/whip/daemon.go` combines locks, configuration, provider discovery, factory construction, kernels, server, gateway, and shutdown. | Small construction helpers and explicit ownership improve readability without a new framework. | + +### Baseline is not yet green + +The [CI run for the starting revision](https://github.com/context-labs/whip/actions/runs/36674593257) +failed. The inspected [SDK job](https://github.com/context-labs/whip/actions/runs/36674593257/job/109756705168) +stopped at `npm audit --omit=dev --audit-level=high`, reporting a high-severity +`brace-expansion` advisory. The later SDK/product acceptance steps in that job +did not run. This is not evidence of an SDK behavior regression, and successful +Go jobs do not establish a green product baseline. + +Resolve baseline failures in separate prerequisite PRs, then run the complete +required gate. Do not lower the audit threshold, drop tests, waive the aggregate +gate, or call skipped checks successful. Any additional failures exposed after +the audit is repaired require the same treatment. This proposal records a +research result, not a completed local acceptance run. + +## 4. Intended boundaries + +Keep one Go module and ordinary `internal` packages. Use constructors and direct +calls. No DI container, service locator, generic repository layer, event bus, +new workflow framework, or package per database table. This fits Go's +[server layout guidance](https://go.dev/doc/modules/layout). + +| Owner | Responsibilities | Dependencies and limits | +| --- | --- | --- | +| `cmd/whip` startup | Configuration, process locks, construction, handoff of ownership, shutdown wiring. | May compose all backend packages. Keep explicit startup order. Add a separate application package only if a real second caller needs it. | +| `internal/daemon` | Server entry points, root registry, root actor, command coordination, existing runtime composition. | Calls provider/host services and storage. It remains the integration point; shrinking it does not require emptying it. | +| Proposed `internal/provider` | Existing provider setup, authentication flows, discovery/catalog selection, host configuration operations used by that service. | Existing config/auth/LLM packages and unchanged protocol types. Must not import `daemon` or own turns. | +| Host MCP component | Import offers, applying host MCP configuration, and current icon lookup used by that surface. | Initially a small component inside `daemon`; separate package only when dependencies justify it. No session MCP lifecycle ownership. | +| Host directory component | Current list/create/pick behavior and OS-specific implementation. | Initially grouped separately inside `daemon`. A later package must preserve existing protocol errors directly, without inventing an error translation model. | +| `internal/session` | SQLite/content persistence, existing durable models, atomic transitions and queries. | No actor or provider construction. Keep existing transaction logic and representations. It may borrow the existing workspace resolver for authority checks. | +| Daemon resource owner | One shared process manager and workspace lock coordinator, passed to tools/MCP/runtime as today. | Ownership is explicit; scope and lifetime stay unchanged. Resource implementations remain in `capability`. | +| Existing `agent`, `rlm`, `tools`, `capability`, `mcp`, `llm` | Existing model loop primitives, kernels, tools, authority enforcement, integration machinery, provider encoders. | Keep their established responsibilities. No broad modernization sweep. | +| Proposed `internal/client` | Existing Go `Client`/`RootClient` and client service methods. | Existing protocol and framing; no dependency on the server/agent runtime implementation. Mechanical Go caller import changes are allowed; client APIs and behavior remain unchanged. | +| Existing `protocol` and `protocoltransport` | Current public representations, schemas, negotiation, and framing. | Preserve contract and representation ownership. Do not force storage to import protocol and create a cycle. | + +The desired direction is startup → daemon orchestration → services/storage, +with clients → protocol/framing. This is a responsibility map, not a claim that +the existing type graph has already become a strict layered architecture. +Check actual imports after each step and document remaining justified edges. + +The provider package initially retains the current atomic host-configuration +update even though some fields concern other domains. Splitting that operation +into independent provider, MCP, and permission-setting writes would violate the +contract. Clear ownership includes making this intentional coupling visible. + +For a cycle, first consider a small interface owned by the caller, with the +same arguments/results and one existing implementation. An interface that +merely exposes the whole daemon or store does not establish a useful boundary. +If breaking a cycle requires a new representation, leave that boundary in the +same package for this effort. + +## 5. Compatibility evidence before structural changes + +### One fixed reference, plus comparison with each PR's base + +Record the development SHA, Go/Node versions, dependency lockfiles, binary +build information, generated-contract digest, SDK artifact digest, and test +commands/results. Preserve a fixed SDK built from the accepted starting +revision. Also compare each PR with its immediate base so regressions can be +attributed to one change. + +Prerequisite bug/dependency repairs must be separately reviewed. Record their +SHAs and the reason for any baseline adjustment. An SDK or product behavior +change requires its own decision; it cannot become an implicit consequence of +getting the reorganization baseline green. + +Use isolated temporary homes, configuration, databases, content directories, +and deterministic providers. Never exercise restart/deletion tests against a +developer's real daemon or data. Live credentials and nondeterministic provider +responses are not a suitable regression oracle. + +### Three complementary checks + +1. **Static contract freeze.** Reject changes to SDK implementation/public + exports, protocol definitions/generator behavior, or contract artifacts. + Schema and generated TypeScript directories are ignored by Git today, so a + clean `git diff` proves nothing about them. Generate both base and candidate + with pinned tooling into isolated directories and compare their contents. + Keep the source/API checks and generation determinism checks as well. +2. **Fixed-client behavioral acceptance.** Run the unchanged baseline SDK and + representative existing client builds against the candidate backend. + Reuse current fixtures and scenarios where possible. The new test runner + must select the candidate daemon binary explicitly: the existing SDK test + fixture builds Go from its own repository path, so importing a baseline + fixture accidentally can test the old backend against itself. Keep any new + orchestration outside frozen SDK source. Record the binary and SDK digests + actually exercised. +3. **Stateful differential scenarios.** Feed the same scripted provider replies + and controlled actions to base and candidate. Compare responses, errors, + ordered observations, provider requests, durable outcomes, trace graphs, + and recovery. Compare raw wire values where stable. Normalize only named + nondeterministic values such as timestamps, random IDs, and temporary paths; + preserve identity relationships, cursor values, event multiplicity, causal + order, and required timing relationships. Never sort event streams or drop + unmatched events to make a comparison pass. + +Do not try to snapshot every concurrent interleaving. Use controlled barriers +to exercise important races, then assert the existing invariants and permitted +outcomes. Avoid sleeps as the main synchronization mechanism. Keep a small +cross-cutting smoke suite and add targeted characterization before each risky +move; do not build another backend or a general simulation framework to test +this refactor. + +### Required preservation matrix + +The named tests below are starting evidence, not an exhaustive allowlist or +proof of sufficient coverage. Review their assertions and fill gaps before the +associated move. Run the full existing gate in addition to targeted tests. + +| Surface | Behavior to demonstrate | Existing starting evidence | +| --- | --- | --- | +| Contract/validation | All registered operations, both transports, negotiation, bad input, unknown fields, error payloads, bounds and empty values. | `runtime_parity_test.go`, `v2_acceptance_test.go`, protocol tests, generated contract checks. | +| Acceptance/identity | Acceptance is durable before execution or provider construction; retries attach to the same work; lost replies do not duplicate side effects. | `TestClientAcceptancePrecedesProviderConstructionAndSurvivesDisconnect`, `TestProtocolCommandRetryAttachesToOneRootExecution`. | +| Cancellation | Before admission, queued, running, completed, disconnected, and shutdown cases preserve their distinct effects; cancel the exact command/turn. | `actor_control_test.go`, `cancel_command_test.go`, `client_control_coverage_test.go`. | +| Reconnect/order | Replay cursor boundaries, snapshot fallback, command identity, no duplicate events, stale-stream rejection, slow clients and overflow. | `root_client_test.go`, `server_test.go`, `subscription_runtime_test.go`, SDK acceptance. | +| Root/child/REPL | Both engines, inherited/overridden model configuration and authority, retained children, mail/reporting, queued prompts, kernel pressure, scratch restoration. | `recursive_runtime*_test.go`, `execution_engine_test.go`, `report_restore_test.go`, `mailbox_delivery_test.go`, RLM tests and deterministic eval. | +| Providers | Default and explicit selection, aliases, request encoding, effort/sampling, auth secrecy, discovery, retries, conflicts, disconnect, compaction and child inheritance. | `provider_*_test.go`, `compaction_fallback_test.go`, `internal/llm` tests. | +| Permissions/resources | Shared manager identity, workspace/symlink checks, delegation and revocation, partial construction failure, process survival/termination, MCP reload. | `workspace_test.go`, `session_test.go`, `filesystem_access_test.go`, capability/session permission tests, MCP tests. | +| Tracing/accounting | Same root/child causal links, model/tool/permission spans, prompt and compaction references, failures, usage/cost, pagination and OTLP content. | `trace_rpc_test.go`, `spans_prompt_test.go`, `command_trace_test.go`, `session/span_test.go`, `otlp_export_test.go`, accounting tests. | +| Persistence/recovery | Existing accepted stores still open; rejected stores remain rejected; committed results and pending work recover identically. Base → candidate → base remains usable. | Migration/checkpoint tests, `v2_crash_test.go`, `child_commit_test.go`, plus a new round-trip compatibility fixture where missing. | +| Product clients | Sessions/tabs/sidebar, history and streaming, tools/permissions/questions, provider/model settings, traces, terminals/browser, attachments, stop/reconnect. | Existing SDK, web/UI browser suites, TUI/ACP integration, desktop/mobile checks; short human smoke at each major boundary. | + +For data rollback, create representative state with the base binary, stop it +cleanly, copy the complete isolated home including content/checkpoints, run the +candidate and write more state, then reopen with the base. Also cover current +crash-recovery fixtures. Compare schema metadata and logical records rather +than SQLite file bytes. No two binaries may own the same home concurrently. + +## 6. Delivery sequence + +Each numbered item describes a reviewable change with its own evidence. If it +needs multiple coherent moves, split it **before implementation**, preserving +the same review-before-next cadence. Aim for roughly 100–500 substantive changed +lines per PR. A large pure move needs a clear move-aware diff and explicit +review scope; it is not permission to include cleanup or behavior changes. + +### Prerequisites: repair and establish the baseline + +- Handle the current dependency-audit failure and any subsequently exposed + failures as independent maintenance/bug PRs. Avoid broad automated upgrades. +- Re-run the full existing CI and acceptance gates. Record a green execution + base and its relationship to the starting revision. +- Enable CI for the stacked PR bases before creating dependent PRs. Currently + `ci.yml` triggers PRs only against `main` or `development`. Extend PR + triggering to this effort's `codex/backend-reorg-*` base branches using the + **same full gate**, and verify it runs on a PR targeting a parent branch. + Do not broaden release/publish triggers or add a reduced substitute workflow. + +These are prerequisites to production-code refactoring, not excuses to bundle +fixes into the first extraction. + +### PR 1 — Establish the frozen-contract regression gate + +**Change:** add the baseline manifest, generated-output comparison, explicit +fixed-SDK/candidate-backend runner, and missing high-value lifecycle/data +characterizations. Build on existing tests. A harness PR and a focused +characterization PR may be needed; review them separately. + +**Risk:** test setup can accidentally compare the wrong binaries or normalize +away the regression it is supposed to detect. + +**Acceptance:** the runner passes on base versus base and on the repaired +execution base, identifies the exact artifacts, and demonstrably rejects a +deliberate test-only response/event-order mismatch. Restore that deliberate +mutation; no product mutation is committed. Existing assertions and gates stay +in force. Keep future baseline updates explicit and reviewable. + +### PR 2 — Separate host MCP configuration from provider ownership + +**Change:** move the existing MCP import/brand-icon responsibility out of +`ProviderService` into a small host component, initially in `daemon`. Update +`mcp_import_service.go` and its direct server/control callers. Preserve existing +protocol types and the icon resolver's lazy initialization, cache, context, +timeout, and shutdown relationship. Do not change session MCP attachment. + +**Risk:** provider shutdown currently supplies cancellation to this work; +splitting the struct must not extend its lifetime or change concurrent access. + +**Acceptance:** import-offer/apply/skip/error/secret tests and host RPC tests +remain unchanged in meaning. Provider operations no longer own MCP import +implementation. One authoritative component still owns icon state. + +### PRs 3a–3b — Prepare and move the provider boundary + +**PR 3a:** consolidate provider operations currently implemented from +`client_control.go`, `query.go`, and `budget.go` into a small callable service +surface while still in the same package. In particular, catalog refresh/read +uses private status and refresh helpers; compaction validation and model +admission also call private methods. Move existing operation bodies rather +than exporting all private helpers. Keep serialization at the existing client +boundary, use unchanged result types, and retain the exact refresh timeouts, +configuration reloads, admission order, and error handling. Locate shared +effort/default helpers through references rather than copying them. Preserve +the single versioned configuration update and its provisioning-lock scope. + +**PR 3b:** move `ProviderService` and its provider implementation files to +`internal/provider`. Keep provider RPC decoding/dispatch in the server and +client RPC methods with the client. Pass the same protocol/configuration +values directly. Preserve the existing separation from `llm` request encoders. +Move service-private tests with the service; keep cross-transport and runtime +integration tests at their existing boundary. Update constructor callers in +daemon and `cmd/whip` mechanically. + +**Risk:** default selection, configuration revisions, validation/secret +redaction, auth cancellation, and background login behavior are easy to alter +while moving helper functions. + +**Acceptance:** the new package has no import of `daemon`; there is one provider +service implementation; provider configuration/auth/catalog tests, fixed-SDK +settings flows, and captured provider request comparisons pass. No encoder, +retry, default, or prompt changes. Review 3a before starting 3b, then review this +stopping point before proceeding. + +### PR 4 — Make startup and construction responsibilities readable + +**Change:** extract small construction functions from `cmd/whip/daemon.go` +for the existing runtime factory and its tool/model/MCP assembly. Keep ordinary +constructor injection. Document ownership transfer and failure cleanup next +to the constructors that perform it. Group host directory operations separately +from the mixed host dispatch file in a separate PR if that move is worthwhile. + +**Risk:** moving a `defer`, context creation, discovery call, or early return +can change initialization and cleanup order even when signatures look the same. + +**Acceptance:** startup/owner locks still precede database access; admission +still precedes expensive provider construction where it does today; partial +factory results close correctly; config refresh and live reload timing remain +unchanged. Runtime acceptance on Linux and macOS passes. No new application +framework or generic container. + +### PR 5 — Move process-manager ownership out of storage + +**Change:** construct the existing shared process manager in the daemon's +composition path and pass it to the current tool, MCP, and runtime consumers. +Remove process construction/ownership from `session.Store` after all callers +are migrated. Internal constructor signatures and test fixtures may change; +public client behavior may not. + +Inventory every store opener, including non-daemon tools and tests. Give each +an explicit cleanup owner where it needs live processes; do not hide a missing +production owner by having a test fixture close leaked resources afterward. + +**Risk:** root-specific `StopRoot`, accepted background work, MCP process +ownership, partial startup, and global shutdown have different lifetimes. + +**Acceptance:** every root/child consumer that shares a manager today still +shares one; root cleanup and process-group behavior are unchanged; manager +closure still occurs at the corresponding shutdown point before database +closure, including failure paths and joined errors. No new process registry, +goroutine, or process policy. Storage no longer owns process lifecycle. + +### PR 6 — Make workspace ownership explicit without changing authority checks + +**Change:** construct the shared workspace lock coordinator at the same host +composition boundary and inject the existing resolver where needed. The store +may retain a borrowed resolver for authority validation. Prefer that limited +dependency over moving security-sensitive checks out of their transactions. + +**Risk:** path canonicalization timing, symlinks, shared mutation locks, and +delegation atomicity. `Workspaces` currently has no close method; do not invent +resource cleanup behavior solely to make lifecycles symmetrical. + +**Acceptance:** preserve manager sharing across roots, exact validation and +transaction order, canonical-path-change rejection, and permitted concurrency. +Storage no longer constructs the live coordinator. Do not claim storage is +independent of capability types; that is neither required nor currently true. + +After PR 6, assess whether the work has delivered sufficient clarity. Provider +separation, startup readability, and explicit runtime resource ownership are +already a useful completed increment. Further steps must justify their risk. + +### PRs 7–8 — Separate native Go clients from server implementation + +The user has confirmed that these mechanical Go client moves and caller import +updates are in scope. Client APIs and behavior remain frozen. + +**PR 7:** isolate only the connection/path/constant plumbing shared by client +and server. `RuntimePaths`, local dialing, initialization constants, and +autostart are mixed with server code today. Reuse `protocoltransport` for +framing. Identify a small neutral home for shared path/connection primitives +without moving daemon ownership/locking policy into the client. Preserve +`Paths` versus side-effect-free `ResolvePaths` semantics. + +**PR 8:** move `Client`, `RootClient`, WebSocket client, and client service +methods to `internal/client`, then update Go consumers in CLI/TUI/ACP and tests +mechanically. Keep reconnect logic, identities, timers, queues and retry policy +intact. Do not add a new SDK or modify the TypeScript SDK. + +**Acceptance:** no import from the Go client package into `daemon`; existing +native-client API behavior and fixed-SDK behavior remain unchanged; TUI/ACP +acceptance, transport tests, replay/cancellation tests, and package builds pass. +Do not retain a forwarding layer in `daemon` as a substitute for migrating the +internal Go callers. + +### PR 9 and later — Smaller actor and persistence responsibilities, selectively + +Do not begin with a wholesale split of `Session`, `RecursiveRuntime`, or +`Store`. Choose one concrete responsibility at a time after refreshing the +reference map and identifying a future change it would make easier. + +Candidate individual PRs, in increasing risk: + +- Group persistence operations by existing responsibility within `session` + without moving durable types or changing SQL/transactions. Do not introduce + repository interfaces per table or a generic unit-of-work abstraction. +- Extract a small tracing bookkeeping helper from the existing span/context + fields, retaining all span call sites, context relationships, and persistence + timing. Keep OTLP export behavior and prompt references intact. +- Extract a focused root-actor helper for configuration activation or MCP + lifecycle bookkeeping. Keep invocation on the same actor/goroutine, under + the same locks and transaction/event boundaries. Do not create another actor, + queue, mutable projection, or scheduling state machine. + +These are candidate follow-ups, not permission for an open-ended cleanup. +Before each, specify exact files/callers, ownership moved, tests, and measurable +benefit in a new inventory row. If the proposed helper needs a broad backpointer +to the whole daemon or a second copy of its state, reconsider the extraction. +Leave the code together when the resulting boundary would be artificial. + +### Closeout — Prove the result and remove only demonstrated redundancy + +Each move deletes its replaced implementation in that same PR. Final cleanup +removes only remaining aliases/helpers with no callers, including build-tag, +reflection, generated-code, CLI dispatch, and test-fixture references. Do not +delete a feature or fallback merely because a static reference search misses +it. Separate any substantial deletion into its own reviewed PR. + +Update `docs/architecture.md` to describe the resulting implementation and +ownership map, including intentional remaining coupling. Follow +[frontend.md](frontend.md) if a Go client move affects documented client +boundaries. Keep a concise PR/evidence ledger in this plan; avoid a second +competing architecture guide. Run full final acceptance and the fixed-client +and data rollback scenarios on the integrated development revision. + +## 7. Lifecycle rules for every extraction + +Before changing ownership, write a small table for the touched resource: +constructor, owner, borrowers, cancellation source, normal close, partial +construction cleanup, restart cleanup, and scope of sharing. Verify actual +behavior, including idempotent or repeated close calls, rather than simplifying +it from memory. + +Current shutdown spans `Server.Close`, `Daemon.Close`, root supervisors, +provider shutdown, process cleanup, SQLite, kernel-manager defers, and the +gateway/startup code. Extracting these into a single `CloseAll` loop without +preserving ordering would be a behavior change. + +Preserve specifically: + +- Connection cancellation versus caller cancellation versus daemon-owned work. +- Root/child cancellation scope and authority revocation. +- Worker/REPL lifetime versus retained session lifetime. +- Shared host resources versus per-root/per-turn resources. +- Lock acquisition order, transaction scope, mailbox ordering, queue bounds, + goroutine launch/join points, and publication-before/after-commit rules. +- Partial construction cleanup, panic recovery, error propagation, and + persistence/accounting work that must settle during shutdown. + +A structural PR can change who holds a pointer. It cannot change when the +pointed-to resource becomes available or ceases to be usable. + +## 8. PR, CI, and review policy + +Use `codex/backend-reorg-<step>-<topic>` branches from the accepted development +base. Preserve each useful change as a separate PR and commit history. Review +the first PR before starting its successor. + +The first PR of each group targets development. Each successor targets its +immediate parent's branch, and work begins only after that parent is approved +and green. Reviewed parents remain open until the group's checkpoint. There is +only one PR under active implementation or review; the other open PRs are +already reviewed dependencies. + +| Merge checkpoint | Group | Evidence required before merging the group | +| --- | --- | --- | +| Baseline and guardrails | Separate prerequisite repairs/CI setup, then PR 1 (split into sequential PRs if needed). | Full baseline is green; stacked-base CI and frozen-client checks work. Land prerequisite repairs before establishing their dependent baseline. | +| Provider boundary | PRs 2, 3a, and 3b. | Host MCP and provider responsibilities are separated; configuration atomicity, provider semantics, and unchanged clients are verified. | +| Resource ownership | PRs 4, 5, and 6. | Startup, process ownership, and workspace ownership are explicit; lifecycle, authority, and data compatibility evidence passes. | +| Native Go client | PRs 7 and 8. | Client/server dependency is separated; Go clients, unchanged TypeScript SDK, reconnect, and cancellation acceptance passes. | +| Selected follow-ups | Each separately agreed actor, tracing, persistence, or cleanup change, or a small group defined before work starts. | The specific benefit is demonstrated and the same compatibility gates pass. No open-ended final stack. | + +At each checkpoint, review the combined result and decide whether the next +group still warrants its risk. Merge approved PRs bottom-up into development, +retargeting and rebasing descendants as needed. After each merge or rebase, +run the required checks on the resulting revision; verify the integrated +development revision before starting the next group. Preserve separate PR +review records. Do not auto-merge or use one final integration-only PR to +repair broken intermediate states. + +Every PR description should contain: + +1. The concrete responsibility being moved and resulting owner. +2. The scope of moves versus substantive edits, including all changed callers. +3. Why behavior is unchanged, identifying sensitive ordering/lifetime points. +4. Tests run on the exact submitted SHA, fixed SDK/backend identities, generated + contract comparison, and applicable data/restart evidence. +5. Any uncovered scenario or remaining coupling, plus the next safe stopping + point. An untested requirement is not marked complete. + +Keep normal CI intact: formatting, vet, `whipvet`, lint, dependency hygiene, +the existing portable race/shuffle suite and **90% coverage floor**, cross +builds, Linux/macOS runtime acceptance, SDK/package/browser/product tests, +docs, desktop, mobile, and distribution checks. Preserve the aggregate `go` +job and all its dependencies. Add frozen-client checks to the required gate. + +`Taskfile.yaml`'s `acceptance` task already covers recursive-agent, capability, +mailbox, reconnect, kernel, TUI/ACP, accounting, and SDK scenarios. Use it with +the existing CI workflow rather than inventing a narrower active test list. +Local full-module build/vet/test checks complement hosted coverage; browser +and TUI tests require their appropriate browser/TTY environment. Use targeted +tests during edits and complete the required gate once the PR is ready. + +Move existing tests with implementation only when necessary. Update +architecture tests to follow the new owners while preserving their assertions. +For example, provider-call checks currently scan the daemon directory and +name `agent_session.go`; after a relevant move, scanning only the old directory +could silently stop enforcing the boundary. Update coverage/package selection +to include new packages, not exclude moved code. + +Add focused import checks for boundaries actually introduced: provider must +not import daemon; client must not import the server implementation; storage +must not construct process managers after that step. Avoid blanket rules that +contradict the existing shared-type graph. + +## 9. Stop, rollback, and scope control + +Stop the current extraction when a frozen contract differs, a behavior test +fails, lifecycle/trace evidence is missing, a gate is skipped, or the move +requires a new representation. Find the structural mistake or revert to the +last green step. Do not repair the failure by modifying clients, weakening +assertions, accepting data loss, or redesigning the protocol. + +If evidence reveals a pre-existing bug, reproduce it on the base, record it, +and propose a separate fix. If that fix must precede the refactor, pause the +dependent PR and resume only after the fix is reviewed and the reference +evidence is updated deliberately. + +Each merged PR must be reversible independently. Schema compatibility removes +the need for a migration rollback, but still test reverting the binary after +candidate writes. If a later PR depends on an earlier one, revert dependent +changes first or restore the last verified development checkpoint. Never +repair test data by deleting a real runtime home. + +Keep the following out of scope unless a future proposal explicitly reopens +them: uniform root/child durable records, a new scheduler, protocol redesign, +SDK state redesign, new permission/budget/retry policies, schema normalization, +new provider defaults, trace redesign, performance tuning, platform removal, +and feature retirement. + +## 10. How to judge whether the work was worth doing + +At the provider, resource-ownership, and native-client checkpoints, record: + +- Which unrelated responsibilities left a broad owner, and the APIs left behind. +- Which dependency edges were removed and which remain intentionally. +- Whether a concrete change—provider setup, MCP import, runtime construction, + or client connection handling—now has an obvious home and focused tests. +- Whether each moved resource has one documented owner and unchanged borrowers + and lifetime, without duplicate mutable state or forwarding layers. +- Added versus removed non-test code, exported symbols, and abstractions; + explain any growth needed for a real boundary. +- The unchanged contract digest and complete behavioral acceptance evidence. + +Reduced file size alone does not count as success. More packages and interfaces +are not inherently improvements. Continue only when the next extraction makes +the backend easier to work on enough to justify its review and regression risk. + +## Research source map + +Primary implementation references at the recorded revision: + +- Startup/lifecycle: `cmd/whip/daemon.go`, `internal/daemon/daemon.go`, + `server.go`, `session.go`, `socket_unix.go`. +- Services: `internal/daemon/provider_*.go`, `mcp_import_service.go`, `host.go`. +- Runtime: `internal/daemon/agent_session.go`, `recursive_runtime.go`, + `spans.go`; `internal/agent`, `internal/rlm`. +- Storage/authority: `internal/session/session.go`, `capability.go`, + `permission.go`, `migrations.go`, `checkpoint.go`, span/OTLP files; + `internal/capability/workspace.go`. +- Clients/contracts: `internal/daemon/client.go`, `root_client.go`, + `websocket_client.go`, `internal/protocol`, `internal/protocoltransport`, + `packages/protocol/scripts/check.mjs`, `packages/sdk/src/testing-node.ts`. +- Gates and guides: `.github/workflows/ci.yml`, `Taskfile.yaml`, + `internal/daemon/architecture_test.go`, `docs/architecture.md`, + `docs/frontend.md`, `packages/sdk/README.md`. + +Research included local source/dependency inspection, language-server reference +mapping, the previous redesign plan and selected GitHub PRs, and current +development CI logs. Full baseline acceptance remains a prerequisite; this +document does not claim it has passed. + +## Execution ledger + +| Step | Revision and PR | Evidence and status | +| --- | --- | --- | +| Dependency-audit prerequisite | [`db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`](https://github.com/context-labs/whip/commit/db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d), [PR #299](https://github.com/context-labs/whip/pull/299) | Only `package-lock.json` changed: 11 `brace-expansion` patch-version entries. Local `npm ci`, production audit at the unchanged high threshold, protocol generation/freshness, all 470 SDK unit tests, client-example build, and packaged SDK smoke passed. Audit reports zero high/critical findings and 15 moderate findings. [Full CI run 36678816413](https://github.com/context-labs/whip/actions/runs/36678816413) is in progress; this is not yet a green execution baseline. | +| Stacked-base CI prerequisite | This PR, based on PR #299. | Extend only the `ci.yml` and `security.yml` pull-request base filters to `codex/backend-reorg-*`. Preserve all existing jobs, the aggregate gate, 90% coverage floor, audit threshold, security scans, and push/schedule/release/publish triggers. Validate the workflow and confirm GitHub starts the full workflow for this non-development-base PR. | + +The prerequisite PRs remain unmerged. Full hosted acceptance and the fixed-client +guardrails must be established before production-code restructuring. From dba610243623b1a7f6f13f910ddec4d6df9bb711 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:58:18 -0700 Subject: [PATCH 24/67] test(ci): accept approved backend stack PR bases --- scripts/test-publish-whipcode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-publish-whipcode.py b/scripts/test-publish-whipcode.py index 6db7f7db9..1e0416ba2 100644 --- a/scripts/test-publish-whipcode.py +++ b/scripts/test-publish-whipcode.py @@ -574,7 +574,7 @@ def test_all_checkouts_explicit_immutable_source(self): def test_shared_gates_still_fail_closed(self): for workflow in [self.ci, self.security]: self.assertIn(' workflow_call:\n', workflow) - self.assertIn(' pull_request:\n branches: [main, development]\n', workflow) + self.assertIn(" pull_request:\n branches: [main, development, 'codex/backend-reorg-*']\n", workflow) self.assertIn(' push:\n branches: [main, development]\n', workflow) self.assertNotIn('continue-on-error:', workflow) for name in ['lint', 'test', 'build', 'runtime', 'driver', 'sdk', 'distribution', 'desktop', 'mobile']: From a57b5261b6225b64451b0d5b06374f721cb83153 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:42:19 -0700 Subject: [PATCH 25/67] test(daemon): isolate inherited provider credentials --- internal/daemon/main_test.go | 79 +++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/internal/daemon/main_test.go b/internal/daemon/main_test.go index f9242de6a..e24e44c9b 100644 --- a/internal/daemon/main_test.go +++ b/internal/daemon/main_test.go @@ -1,14 +1,22 @@ package daemon import ( + "encoding/json" + "errors" "fmt" + "net/http" "os" + "os/exec" "path/filepath" + "sync/atomic" "testing" + + "github.com/context-labs/whip/internal/config" ) -// Model requests in tests must not depend on, or expose, the developer's -// standing instructions or installed skills. Tests may override these fixtures. +// Model requests and discovery in tests must not depend on, or expose, the +// developer's credentials, standing instructions or installed skills. Tests may +// override these fixtures. func TestMain(m *testing.M) { home, err := os.MkdirTemp("", "whip-daemon-test-home-") if err != nil { @@ -21,6 +29,13 @@ func TestMain(m *testing.M) { if err == nil { err = os.Unsetenv("XDG_CONFIG_HOME") // OpenCode discovery would read it before HOME } + if err == nil { + for _, name := range providerTestEnvironment() { + if err = os.Unsetenv(name); err != nil { + break + } + } + } if err != nil { os.RemoveAll(home) fmt.Fprintln(os.Stderr, err) @@ -30,3 +45,63 @@ func TestMain(m *testing.M) { os.RemoveAll(home) os.Exit(code) } + +func providerTestEnvironment() []string { + names := []string{"OPENAI_BASE_URL", "OPENAI_API_BASE"} + for _, preset := range config.ProviderPresets() { + names = append(names, preset.EnvironmentVariables...) + } + return names +} + +func TestDaemonTestEnvironment(t *testing.T) { + const child = "WHIP_TEST_PROVIDER_ENV_CHILD" + if os.Getenv(child) == "" { + command := exec.CommandContext(t.Context(), os.Args[0], "-test.run=^TestDaemonTestEnvironment$") + command.Env = append(os.Environ(), child+"=1") + for _, name := range providerTestEnvironment() { + command.Env = append(command.Env, name+"=inherited-provider-fixture") + } + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("inherited provider environment was not isolated: %v\n%s", err, output) + } + return + } + + // Exercise TestMain in a fresh process with harmless inherited keys. Trap + // every HTTP request so a regression cannot reach a real provider. + var requests atomic.Int64 + previous := http.DefaultTransport + http.DefaultTransport = catalogTransport(func(*http.Request) (*http.Response, error) { + requests.Add(1) + return nil, errors.New("unexpected provider request in isolated tests") + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + for _, name := range providerTestEnvironment() { + if _, exists := os.LookupEnv(name); exists { + t.Errorf("inherited %s survived TestMain", name) + } + } + cfg := &config.Config{Providers: map[string]config.Provider{}} + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + if got := cfg.EffectiveProviders(); len(got) != 0 { + t.Errorf("empty fixture discovered %d inherited providers", len(got)) + } + service := NewProviderService(t.Context(), "isolated-test-environment") + t.Cleanup(service.Close) + if _, err := queryProviderCatalogs(t.Context(), service, json.RawMessage(`{}`)); err != nil { + t.Fatal(err) + } + if got := requests.Load(); got != 0 { + t.Errorf("empty fixture made %d provider requests", got) + } + + // Tests can still opt into discovery explicitly after suite isolation. + t.Setenv(config.OpenRouterEnvVar, "explicit-provider-fixture") + providers := cfg.EffectiveProviders() + if provider, ok := providers["openrouter"]; !ok || len(providers) != 1 || !provider.KeyStatus(cfg).Available { + t.Fatal("explicit test key did not discover exactly its provider") + } +} From 722b49321f3cb2a70c8d829911279ffd79caf0a0 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:57:12 -0700 Subject: [PATCH 26/67] test(ui): await sheet focus before scroll assertions --- packages/ui/tests/browser.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ui/tests/browser.mjs b/packages/ui/tests/browser.mjs index 239831001..2b54ebac4 100644 --- a/packages/ui/tests/browser.mjs +++ b/packages/ui/tests/browser.mjs @@ -182,6 +182,7 @@ try { await page.keyboard.press('Escape'); await page.getByRole('button', {name: 'Open sheet example'}).click(); + await expect(popup.getByRole('button', {name: 'Close', exact: true})).toBeFocused(); const sheet = await popup.boundingBox(); expect(sheet.y).toBe(0); expect(sheet.height).toBe(height); From a26c641fdf994ccc87a61efe3df4a5a342ba645b Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:53:02 -0700 Subject: [PATCH 27/67] test: guard backend reorganization compatibility --- .github/workflows/ci.yml | 46 +++- scripts/backend-compat/README.md | 75 +++++++ scripts/backend-compat/baseline.json | 20 ++ scripts/backend-compat/compare.mjs | 49 +++++ scripts/backend-compat/compare.test.mjs | 41 ++++ scripts/backend-compat/fixture.mjs | 74 +++++++ scripts/backend-compat/run.mjs | 119 ++++++++++ scripts/backend-compat/scenarios.mjs | 281 ++++++++++++++++++++++++ 8 files changed, 704 insertions(+), 1 deletion(-) create mode 100644 scripts/backend-compat/README.md create mode 100644 scripts/backend-compat/baseline.json create mode 100644 scripts/backend-compat/compare.mjs create mode 100644 scripts/backend-compat/compare.test.mjs create mode 100644 scripts/backend-compat/fixture.mjs create mode 100644 scripts/backend-compat/run.mjs create mode 100644 scripts/backend-compat/scenarios.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9e0ad4b7..4677b24b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -288,9 +288,51 @@ jobs: mobile: uses: ./.github/workflows/mobile.yml + # Fixed SDK from the accepted development revision against explicit binaries. + # This complements every existing gate; it does not replace product acceptance. + compatibility: + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-15] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: ${{ github.sha }} + fetch-depth: 0 + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + with: + node-version: 24 + cache: npm + - name: Contract freeze, differential SDK and data rollback + env: + COMPATIBILITY_BASE: ${{ github.event.pull_request.base.sha || github.event.before || github.sha }} + run: | + # PRs use their immediate parent branch; initial push/reusable runs + # without a previous commit use the current commit for attribution. + if [ "$COMPATIBILITY_BASE" = 0000000000000000000000000000000000000000 ]; then COMPATIBILITY_BASE="$GITHUB_SHA"; fi + node scripts/backend-compat/run.mjs --candidate "$GITHUB_WORKSPACE" --base "$COMPATIBILITY_BASE" --output "$RUNNER_TEMP/backend-compat" + - name: Compatibility evidence + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: backend-compat-${{ runner.os }} + path: | + ${{ runner.temp }}/backend-compat/evidence.json + ${{ runner.temp }}/backend-compat/command-*.log + ${{ runner.temp }}/backend-compat/runs-*/**/*.json + ${{ runner.temp }}/backend-compat/runs-*/**/*.log + retention-days: 14 + # Required aggregate: failed or skipped dependencies must fail, never go green. go: - needs: [lint, test, build, runtime, driver, sdk, docs, distribution, desktop, mobile] + needs: [lint, test, build, runtime, driver, sdk, docs, distribution, desktop, mobile, compatibility] if: always() runs-on: ubuntu-latest steps: @@ -302,6 +344,7 @@ jobs: echo "runtime=${{ needs.runtime.result }}" echo "driver=${{ needs.driver.result }}" echo "sdk=${{ needs.sdk.result }}" + echo "compatibility=${{ needs.compatibility.result }}" echo "docs=${{ needs.docs.result }}" echo "distribution=${{ needs.distribution.result }}" echo "desktop=${{ needs.desktop.result }}" @@ -312,6 +355,7 @@ jobs: [ "${{ needs.runtime.result }}" = success ] || exit 1 [ "${{ needs.driver.result }}" = success ] || exit 1 [ "${{ needs.sdk.result }}" = success ] || exit 1 + [ "${{ needs.compatibility.result }}" = success ] || exit 1 [ "${{ needs.docs.result }}" = success ] || exit 1 [ "${{ needs.distribution.result }}" = success ] || exit 1 [ "${{ needs.desktop.result }}" = success ] || exit 1 diff --git a/scripts/backend-compat/README.md b/scripts/backend-compat/README.md new file mode 100644 index 000000000..b9bb74128 --- /dev/null +++ b/scripts/backend-compat/README.md @@ -0,0 +1,75 @@ +# Frozen backend compatibility gate + +Run from the candidate checkout, using Node 24 and the Go version in `go.mod`: + +```sh +node scripts/backend-compat/run.mjs --candidate "$PWD" --base <immediate-parent-commit-sha> --output /tmp/whip-backend-compat +``` + +Use a new output directory for review evidence. The runner archives the pinned +revision in `baseline.json`, installs its exact dependencies, generates its +protocol, and builds its SDK. It separately regenerates candidate artifacts and +compiles the fixed reference, explicit immediate PR base, and candidate Go +integration binaries. PR CI supplies its actual base SHA; push runs use the +previous commit, with the current commit as the fallback when no previous +revision is available. The baseline SDK is loaded by absolute +path from the baseline archive and is never rebuilt from candidate Go types. +The fixture launcher executes the selected binary directly; it does not use the +SDK test helper that compiles Go from its own repository. + +`evidence.json` records source revisions, actual tool versions, binary and SDK +hashes, generated protocol hashes, commands and completed checks. Local +`candidateRevision` identifies HEAD and `candidateDiff` records tracked edits; +stage or commit new Go files before running so added implementation sources are +included in that evidence. CI tests the checked-out commit. The initial local +harness validation contains only scripts/CI edits, so its daemon implementation +is exactly its recorded parent revision. Failed runs +retain logs and isolated homes for diagnosis. These homes contain synthetic test +data; fixture processes receive a minimal environment without inherited provider +credentials. Linux and macOS run this job, and the existing aggregate gate +requires both. All pre-existing SDK, browser, Go, platform and distribution checks +remain required. + +The checks are complementary: + +- Tracked SDK/protocol/generator/framing/schema source stays identical to the + fixed revision. Schema and generated TypeScript are ignored by Git, so both + sides are freshly generated and compared file by file. Built SDK artifacts + must also match exactly. +- Fixed SDK smoke scenarios run twice against baseline to calibrate and once + against candidate and immediate PR base, independently for Unix and WebSocket. They compare full + selected responses/errors, ordered live and replay events, snapshots/history, + content-backed streams, provider configuration, configuration conflicts, + retry identity and cursor rejection. +- Lifecycle checks exercise disconnect and waiter abort without cancelling + accepted work, explicit cancellation, real process crash, queued attachment + recovery, and no repeated uncertain effects. These check allowed outcomes, + rather than equating incidental response/notification interleaving or the + accepted command's transient queued/running status. +- Both fixed and immediate base → candidate → base rollback cover real root and retained child + checkpoints in Starlark and QuickJS, new state written by candidate, chunked + content, unchanged schema, SQLite integrity, checkpoint and content hashes, + complete trace pages and OTLP exports. A baseline-only round trip calibrates + this fixture first. Trace pages and export documents are compared across + binaries on identical persisted state, preserving every field except the + trace page's current server clock. + +The smoke normalizer has a narrow list of random identity and clock fields. +It preserves identity relationships, exact cursor/sequence values, omissions, +nulls, empty values, error details, event order/multiplicity and content digests. +A stream larger than the existing supervisor's 32 KiB coalescing threshold +forces two separate fixture fragments; smaller fragments could validly coalesce +and would be a poor exact-event regression oracle. Comparator tests prove that +response, omission, error, cursor, event order/count and identity mutations fail. + +This is a cross-cutting regression gate, not exhaustive behavioral equivalence. +It does not replace existing provider encoding/retry tests, detailed trace body +and pagination tests, REPL/mail/budget tests, or product acceptance. Add focused +characterizations before a move when those existing assertions leave a gap. +Provider configuration checks do not contact live model providers. Arbitrary +concurrent schedules are checked by existing invariants, not by sorting events +or accepting a candidate's new expected transcript. + +Changing the baseline pin or frozen paths requires an explicit compatibility +decision. Dependency maintenance is separate and does not silently replace the +original SDK oracle. Do not update assertions to make a structural change pass. diff --git a/scripts/backend-compat/baseline.json b/scripts/backend-compat/baseline.json new file mode 100644 index 000000000..4f9a5df27 --- /dev/null +++ b/scripts/backend-compat/baseline.json @@ -0,0 +1,20 @@ +{ + "revision": "271c0f8d2a35648d1b45056d57432590b783483c", + "protocol": "6.9", + "schemaVersion": 21, + "schemaIdentity": "whip-recursive-runtime-v21", + "frozenPaths": [ + "packages/sdk", + "packages/protocol", + "internal/protocol", + "internal/protocoltransport", + "cmd/whip-contract", + "internal/session/migrations.go", + "internal/session/*_migration.go" + ], + "generatedPaths": [ + "packages/protocol/schema", + "packages/protocol/generated" + ], + "note": "The original development SDK remains the reference. Separately reviewed dependency repairs do not move this pin. Update this manifest only through an explicit compatibility decision." +} diff --git a/scripts/backend-compat/compare.mjs b/scripts/backend-compat/compare.mjs new file mode 100644 index 000000000..7f85bd831 --- /dev/null +++ b/scripts/backend-compat/compare.mjs @@ -0,0 +1,49 @@ +import assert from 'node:assert/strict'; + +const identityKeys = new Set(['runtime_id', 'connection_id', 'root_id', 'agent_id', 'turn_id', 'subscription_id', 'reference_id', 'parent_id', 'trace_id', 'span_id', 'call_id', 'invocation_id', 'operation_id']); +const dateKeys = new Set(['created_at', 'updated_at', 'sent_at', 'started_at', 'completed_at', 'finished_at', 'ended_at', 'last_active_at']); +const nanoKeys = new Set(['start_ns', 'end_ns', 'server_time_ns', 'startTimeUnixNano', 'endTimeUnixNano']); + +// Normalize named nondeterminism only. Array order, multiplicity, empty values, +// revisions, cursors, error messages and content digests remain significant. +export function normalize(value, { directory = '', identities = [] } = {}) { + const ids = new Map(identities); + let next = 0; + const identify = raw => { if (raw && !ids.has(raw)) ids.set(raw, `<identity:${++next}>`); }; + function discover(item) { + if (Array.isArray(item)) { for (const child of item) discover(child); return; } + if (!item || typeof item !== 'object') return; + if (item.started_at && item.finished_at) assert.ok(Date.parse(item.finished_at) >= Date.parse(item.started_at), 'turn finished before it started'); + if (item.start_ns && item.end_ns && item.end_ns !== '0') assert.ok(BigInt(item.end_ns) >= BigInt(item.start_ns), 'span ended before it started'); + for (const [key, child] of Object.entries(item)) { + if (identityKeys.has(key) && typeof child === 'string') identify(child); + if (key === 'id' && typeof child === 'string' && (item.trace_id || item.parent_id !== undefined || item.kind === 'agent')) identify(child); + discover(child); + } + } + discover(value); + function visit(item, key = '') { + if (Array.isArray(item)) return item.map(child => visit(child)); + if (item && typeof item === 'object') return Object.fromEntries(Object.entries(item).map(([name, child]) => [name, visit(child, name)])); + if (typeof item === 'string') { + if (dateKeys.has(key) && item !== '') { + assert.ok(Number.isFinite(Date.parse(item)), `invalid ${key}: ${item}`); + return '<timestamp>'; + } + if (nanoKeys.has(key)) { + assert.match(item, /^\d+$/, `invalid ${key}`); + return item === '0' ? '0' : '<nanoseconds>'; + } + if (ids.has(item)) return ids.get(item); + const capability = /^(files|mcp|shell|tools):(.+)$/.exec(item); + if (capability && ids.has(capability[2])) return capability[1] + ':' + ids.get(capability[2]); + if (directory && item.includes(directory)) return item.replaceAll(directory, '<fixture>'); + } + return item; + } + return visit(value); +} + +export function compare(expected, actual, label = 'compatibility transcript') { + assert.deepEqual(actual, expected, label); +} diff --git a/scripts/backend-compat/compare.test.mjs b/scripts/backend-compat/compare.test.mjs new file mode 100644 index 000000000..dd3456996 --- /dev/null +++ b/scripts/backend-compat/compare.test.mjs @@ -0,0 +1,41 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { compare, normalize } from './compare.mjs'; + +const transcript = () => ({ response: { value: null, cursor: '3' }, error: { code: -32000, message: 'conflict', data: { kind: 'conflict' } }, events: [ + { seq: '1', kind: 'started', payload: { root_id: 'root-a', turn_id: 'turn-a', created_at: '2026-01-01T00:00:00Z' } }, + { seq: '2', kind: 'text', payload: { root_id: 'root-a', turn_id: 'turn-a', text: 'first' } }, + { seq: '3', kind: 'ended', payload: { root_id: 'root-a', turn_id: 'turn-a' } }, +] }); + +test('only named nondeterminism changes; identity relationships remain intact', () => { + const left = transcript(), right = transcript(); + for (const event of right.events) { event.payload.root_id = 'root-b'; event.payload.turn_id = 'turn-b'; } + right.events[0].payload.created_at = '2026-03-01T00:00:00Z'; + compare(normalize(left), normalize(right)); +}); + +for (const [name, mutate] of Object.entries({ + response: value => { value.response.value = ''; }, + cursor: value => { value.response.cursor = '4'; }, + omission: value => { delete value.response.value; }, + error: value => { value.error.message = 'different conflict'; }, + order: value => { value.events.reverse(); }, + missing: value => { value.events.pop(); }, + duplicate: value => { value.events.push(value.events[2]); }, + identity: value => { value.events[2].payload.turn_id = 'different-turn'; }, + payload: value => { value.events[1].payload.text = 'changed'; }, +})) test(`rejects deliberate ${name} regression`, () => { + const changed = transcript(); mutate(changed); + assert.throws(() => compare(normalize(transcript()), normalize(changed)), assert.AssertionError); +}); + +test('invalid clock values fail instead of disappearing during normalization', () => { + assert.throws(() => normalize({ created_at: 'invalid' })); + assert.throws(() => normalize({ end_ns: '-1' })); +}); + +test('reversed turn and span times fail before normalization', () => { + assert.throws(() => normalize({ started_at: '2026-01-02T00:00:00Z', finished_at: '2026-01-01T00:00:00Z' })); + assert.throws(() => normalize({ start_ns: '2', end_ns: '1' })); +}); diff --git a/scripts/backend-compat/fixture.mjs b/scripts/backend-compat/fixture.mjs new file mode 100644 index 000000000..6dba69c3e --- /dev/null +++ b/scripts/backend-compat/fixture.mjs @@ -0,0 +1,74 @@ +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import { join, isAbsolute } from 'node:path'; +import { setTimeout as delay } from 'node:timers/promises'; + +export async function eventually(check, label, timeout = 30_000) { + const end = Date.now() + timeout; + let last; + while (Date.now() < end) { + try { const value = await check(); if (value) return value; } catch (error) { last = error; } + await delay(25); + } + throw new Error(`Timed out: ${label}`, { cause: last }); +} + +// Deliberately independent of SDK testing-node: that helper builds its own Go +// checkout. This launcher executes only the explicitly supplied artifact. +export async function startFixture(binary, directory, { agents = false } = {}) { + assert.ok(isAbsolute(binary), 'fixture binary must be absolute'); + await mkdir(join(directory, 'public'), { recursive: true }); + let generation = 1; + try { generation += JSON.parse(await readFile(join(directory, 'bridge.json'))).generation; } + catch (error) { if (error.code !== 'ENOENT') throw error; } + // Do not inherit live provider credentials, configuration paths or telemetry. + const env = Object.fromEntries(['PATH', 'TMPDIR', 'TEMP', 'TMP', 'SYSTEMROOT'].flatMap(key => process.env[key] ? [[key, process.env[key]]] : [])); + Object.assign(env, { WHIP_SDK_FIXTURE_DIR: directory, WHIP_SDK_FIXTURE_LIFETIME: '15m', WHIP_SDK_AGENTS_FIXTURE: agents ? '1' : '0' }); + const child = spawn(binary, ['-test.run=^TestV2SDKBridge$', '-test.timeout=16m', '-test.v'], { env, stdio: ['ignore', 'pipe', 'pipe'] }); + let output = ''; + child.stdout.on('data', data => { output += data; }); + child.stderr.on('data', data => { output += data; }); + const exited = new Promise((resolve, reject) => { + child.once('error', reject); + child.once('exit', (code, signal) => resolve({ code, signal })); + }); + let info; + try { + info = await eventually(async () => { + if (child.exitCode !== null || child.signalCode !== null) throw new Error(`fixture exited: ${output}`); + const value = JSON.parse(await readFile(join(directory, 'bridge.json'))); + return value.generation === generation && value; + }, `fixture generation ${generation}`); + } catch (error) { + child.kill('SIGKILL'); await exited; + await writeFile(join(directory, `process-${generation}.log`), output); + throw new Error(`Cannot start ${binary}: ${output}`, { cause: error }); + } + let closed = false; + return { + info, directory, + async effects() { + const response = await fetch(info.frontend + '/control/effects', { signal: AbortSignal.timeout(3000) }); + assert.ok(response.ok); + return (await response.text()).trim().split('\n').filter(Boolean).map(JSON.parse); + }, + async release(key) { + const response = await fetch(info.frontend + '/control/release?key=' + encodeURIComponent(key), { method: 'POST', signal: AbortSignal.timeout(3000) }); + assert.ok(response.ok); + }, + async close(crash = false) { + if (closed) return; + closed = true; + if (crash) child.kill('SIGKILL'); + else await fetch(info.frontend + '/done', { method: 'POST', signal: AbortSignal.timeout(3000) }).catch(() => {}); + const timer = setTimeout(() => child.kill('SIGKILL'), 10_000); + const result = await exited; + clearTimeout(timer); + await writeFile(join(directory, `process-${generation}.log`), output); + assert.ok(!output.includes('WARNING: DATA RACE'), output); + if (crash) assert.equal(result.signal, 'SIGKILL', output); + else assert.deepEqual(result, { code: 0, signal: null }, output); + }, + }; +} diff --git a/scripts/backend-compat/run.mjs b/scripts/backend-compat/run.mjs new file mode 100644 index 000000000..63a7b2715 --- /dev/null +++ b/scripts/backend-compat/run.mjs @@ -0,0 +1,119 @@ +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; +import { parseArgs } from 'node:util'; +import { fileURLToPath } from 'node:url'; +import { compare } from './compare.mjs'; +import { loadSDK, smoke, lifecycle, rollback } from './scenarios.mjs'; + +const { values } = parseArgs({ options: { candidate: { type: 'string' }, base: { type: 'string' }, output: { type: 'string' } } }); +assert.ok(values.candidate && values.base, 'usage: node scripts/backend-compat/run.mjs --candidate /absolute/checkout --base <parent SHA> [--output /artifacts]'); +assert.match(values.base, /^[0-9a-f]{40}$/, 'base must be an explicit full commit SHA'); +assert.equal(process.versions.node.split('.')[0], '24', 'use the repository Node 24 toolchain'); +const candidate = resolve(values.candidate); +const output = values.output ? resolve(values.output) : await mkdtemp(join(tmpdir(), 'whip-compat-')); +const baseline = join(output, 'baseline'); +const parent = join(output, 'pr-base'); +await mkdir(output, { recursive: true }); +assert.deepEqual(await readdir(output), [], 'output must be empty; use a fresh directory to prevent stale baseline artifacts'); +const manifest = JSON.parse(await readFile(new URL('./baseline.json', import.meta.url))); +const evidence = { status: 'running', manifest, candidate, output, node: process.version, commands: [], results: {} }; +const digest = bytes => createHash('sha256').update(bytes).digest('hex'); +async function command(program, args, cwd = candidate) { + console.log(`compatibility: ${program} ${args.join(' ')}`); + const child = spawn(program, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] }); + const chunks = [], errors = []; + child.stdout.on('data', data => chunks.push(data)); child.stderr.on('data', data => errors.push(data)); + const code = await new Promise((resolve, reject) => { child.on('error', reject); child.on('exit', resolve); }); + const stdout = Buffer.concat(chunks), stderr = Buffer.concat(errors); + const log = `command-${evidence.commands.length}.log`; + evidence.commands.push({ program, args, cwd, code, log }); + const logged = program === 'git' && args[0] === 'archive' ? Buffer.from(`archive sha256=${digest(stdout)}\n`) : stdout; + await writeFile(join(output, log), Buffer.concat([logged, stderr])); + assert.equal(code, 0, `${program} failed; see ${join(output, log)}\n${stderr.toString().slice(-4000)}`); + return stdout; +} +async function tree(path) { + const files = {}; + async function visit(relative = '') { + for (const entry of (await readdir(join(path, relative), { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) { + const name = join(relative, entry.name); + if (entry.isDirectory()) await visit(name); + else { assert.ok(entry.isFile(), `unexpected artifact symlink ${name}`); files[name] = digest(await readFile(join(path, name))); } + } + } + await visit(); return files; +} +const baseBinary = join(output, 'baseline-daemon.test'), candidateBinary = join(output, 'candidate-daemon.test'); +const parentBinary = values.base === manifest.revision ? baseBinary : join(output, 'pr-base-daemon.test'); +try { + evidence.go = (await command('go', ['version'])).toString().trim(); + evidence.parentRevision = (await command('git', ['rev-parse', '--verify', values.base + '^{commit}'])).toString().trim(); + evidence.candidateRevision = (await command('git', ['rev-parse', 'HEAD'])).toString().trim(); + evidence.candidateDiff = (await command('git', ['diff', '--binary', 'HEAD'])).toString(); + // Comparing the working tree also rejects uncommitted contract changes. + const changed = (await command('git', ['diff', '--name-only', manifest.revision, '--', ...manifest.frozenPaths])).toString().trim(); + assert.equal(changed, '', `frozen contract source changed:\n${changed}`); + const added = (await command('git', ['ls-files', '--others', '--exclude-standard', '--', ...manifest.frozenPaths])).toString().trim(); + assert.equal(added, '', `untracked contract source added:\n${added}`); + { + await mkdir(baseline, { recursive: true }); + const archive = await command('git', ['archive', manifest.revision]); + const archivePath = join(output, 'baseline.tar'); await writeFile(archivePath, archive); + await command('tar', ['-xf', archivePath, '-C', baseline]); await rm(archivePath); + for (const checkout of [baseline, candidate]) { + await command('npm', ['ci', '--ignore-scripts', '--no-audit', '--no-fund'], checkout); + for (const path of manifest.generatedPaths) await rm(join(checkout, path), { recursive: true, force: true }); + await command('npm', ['run', 'generate'], checkout); + await command('npm', ['run', 'build'], checkout); + } + await command('go', ['test', '-c', '-tags=integration', '-o', baseBinary, './internal/daemon'], baseline); + await command('go', ['test', '-c', '-tags=integration', '-o', candidateBinary, './internal/daemon'], candidate); + if (parentBinary !== baseBinary) { + await mkdir(parent); + const archivePath = join(output, 'pr-base.tar'); + await writeFile(archivePath, await command('git', ['archive', values.base])); + await command('tar', ['-xf', archivePath, '-C', parent]); await rm(archivePath); + await command('go', ['test', '-c', '-tags=integration', '-o', parentBinary, './internal/daemon'], parent); + } + } + for (const path of manifest.generatedPaths) compare(await tree(join(baseline, path)), await tree(join(candidate, path)), `fresh generated ${path}`); + compare(await tree(join(baseline, 'packages/sdk/dist')), await tree(join(candidate, 'packages/sdk/dist')), 'compiled SDK artifact freeze'); + evidence.artifacts = { baselineBinary: digest(await readFile(baseBinary)), parentBinary: digest(await readFile(parentBinary)), candidateBinary: digest(await readFile(candidateBinary)), sdk: await tree(join(baseline, 'packages/sdk/dist')), protocol: await tree(join(baseline, 'packages/protocol/generated')), lockfile: digest(await readFile(join(baseline, 'package-lock.json'))) }; + await command(process.execPath, ['--test', fileURLToPath(new URL('./compare.test.mjs', import.meta.url))]); + const sdk = await loadSDK(baseline); + // Every invocation gets new state, including repeated calibration runs. + const runs = await mkdtemp(join(output, 'runs-')); + for (const transport of ['unix', 'websocket']) { + const reference = await smoke(sdk, baseBinary, join(runs, `base-${transport}`), transport); + const calibration = await smoke(sdk, baseBinary, join(runs, `calibration-${transport}`), transport); + await writeFile(join(runs, `reference-${transport}.json`), JSON.stringify(reference, null, 2)); + await writeFile(join(runs, `calibration-${transport}.json`), JSON.stringify(calibration, null, 2)); + compare(reference, calibration, `${transport} base-versus-base calibration`); + const responseMutation = structuredClone(reference); responseMutation.updated.max_retries++; + assert.throws(() => compare(reference, responseMutation), assert.AssertionError); + const orderMutation = structuredClone(reference); orderMutation.live.reverse(); + assert.throws(() => compare(reference, orderMutation), assert.AssertionError); + evidence.results[`${transport}MutationDetection`] = 'passed: actual response and event order mutations rejected'; + const actual = await smoke(sdk, candidateBinary, join(runs, `candidate-${transport}`), transport); + await writeFile(join(runs, `candidate-${transport}.json`), JSON.stringify(actual, null, 2)); + compare(reference, actual, `${transport} fixed-SDK differential`); + const parentTranscript = parentBinary === baseBinary ? reference : await smoke(sdk, parentBinary, join(runs, `parent-${transport}`), transport); + await writeFile(join(runs, `parent-${transport}.json`), JSON.stringify(parentTranscript, null, 2)); + compare(parentTranscript, actual, `${transport} immediate-PR-base differential`); + evidence.results[transport] = 'passed: calibrated response/error/event transcript'; + } + for (const [name, binary] of [['baseline', baseBinary], ['candidate', candidateBinary]]) { + await lifecycle(sdk, binary, join(runs, `${name}-lifecycle`)); evidence.results[`${name}Lifecycle`] = 'passed'; + } + await rollback(sdk, baseBinary, baseBinary, join(runs, 'rollback-calibration')); + await rollback(sdk, baseBinary, candidateBinary, join(runs, 'rollback-candidate')); + if (parentBinary !== baseBinary) await rollback(sdk, parentBinary, candidateBinary, join(runs, 'rollback-parent')); + evidence.results.rollback = 'passed: fixed and immediate bases; both engines, retained root/child state, content, schema, trace/export'; + evidence.status = 'passed'; + console.log(`Compatibility checks passed. Evidence: ${join(output, 'evidence.json')}`); +} catch (error) { evidence.status = 'failed'; evidence.failure = { name: error.name, message: error.message }; throw error; } +finally { await writeFile(join(output, 'evidence.json'), JSON.stringify(evidence, null, 2)); } diff --git a/scripts/backend-compat/scenarios.mjs b/scripts/backend-compat/scenarios.mjs new file mode 100644 index 000000000..753910548 --- /dev/null +++ b/scripts/backend-compat/scenarios.mjs @@ -0,0 +1,281 @@ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { cp, mkdir, readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { DatabaseSync } from 'node:sqlite'; +import { startFixture, eventually } from './fixture.mjs'; +import { normalize } from './compare.mjs'; + +const deadline = () => ({ signal: AbortSignal.timeout(30_000) }); +const hash = value => createHash('sha256').update(value).digest('hex'); +const plain = value => JSON.parse(JSON.stringify(value)); +let cellSequence = 0; +const cell = code => 'Run this cell:\n\n```cell\n' + code + '\n```'; + +export async function loadSDK(baseline) { + return { ...await import(pathToFileURL(join(baseline, 'packages/sdk/dist/index.js'))), ...await import(pathToFileURL(join(baseline, 'packages/sdk/dist/node.js'))) }; +} + +async function connect(sdk, fixture, transport, clientId, wire = []) { + const factory = transport === 'unix' ? sdk.unixSocket(fixture.info.socket) : sdk.webSocket(fixture.info.endpoint); + const endpoint = async (handlers, signal) => factory({ ...handlers, message(message) { + wire.push(JSON.parse(message)); handlers.message(message); + } }, signal); + const client = sdk.createWhipClient({ endpoint, clientId, clientKind: 'automation', reconnect: false }); + await client.connect(); + return client; +} + +async function createRoot(client, cwd, engine, commandId = 'create-root') { + const result = await client.submit('session.create', { kind: 'agent', cwd, model: 'model', provider: 'provider', ...(engine ? { execution_engine: engine } : {}) }, { commandId }).result(deadline()); + assert.equal(result.status, 'succeeded', JSON.stringify(result)); + return result.result.root_id; +} + +async function errorOf(action) { + try { await action(); } catch (error) { assert.ok(error.rpc, `expected wire RPC error, got ${error}`); return plain(error.rpc); } + assert.fail('request unexpectedly succeeded'); +} + +export async function smoke(sdk, binary, directory, transport) { + const fixture = await startFixture(binary, directory); + const wire = []; + let client, stream; + try { + client = await connect(sdk, fixture, transport, 'compatibility', wire); + const initialization = client.requireConnected(); + const { runtime_id, connection_id, protocol_major, protocol_minor, capabilities, negotiated_capabilities, operations, limits, execution_engines, default_execution_engine } = initialization; + const configuration = await client.configuration.get(); + const updated = await client.configuration.update({ revision: configuration.revision, max_retries: configuration.max_retries + 1 }); + const configurationConflict = await errorOf(() => client.configuration.update({ revision: configuration.revision, max_retries: configuration.max_retries + 2 })); + const provider = await client.providers.get('openai'); + const unknownProvider = await errorOf(() => client.providers.get('compatibility-missing')); + const rootId = await createRoot(client, directory); + const initial = await client.session(rootId).snapshot(); + stream = await client.events.subscribe(rootId, initial.cursor, deadline()); + // Larger than the supervisor's 32 KiB coalescing limit: both fragments must + // remain separate regardless of scheduling, and each exercises content. + const text = 'A'.repeat(16385) + 'B'.repeat(16385); + const command = client.session(rootId).submit({ text }, { commandId: 'ordered-input' }); + const accepted = await command.accepted(deadline()); + assert.ok(['queued', 'running', 'succeeded'].includes(accepted.status)); + const outcome = await command.result(deadline()); + assert.equal(outcome.status, 'succeeded'); + const replay = await client.call('events.replay', { root_id: rootId, cursor: initial.cursor, limit: 1000 }); + await eventually(() => wire.filter(message => message.method === 'event').some(message => message.params.event.seq === replay.latest), 'live events reach durable cursor'); + const live = wire.filter(message => message.method === 'event').map(message => message.params.event); + const replayComparable = replay.events.map(event => ({ ...event, subscription_id: stream.id })); + assert.deepEqual(live, replayComparable, 'live events differ from durable order/multiplicity'); + const fragments = replay.events.filter(event => event.kind === 'stream.text'); + assert.equal(fragments.length, 2); + const bodies = []; + for (const event of fragments) bodies.push(await client.content(event.payload.content, { rootId }).readJSON({ maxBytes: 1 << 20 })); + assert.equal(bodies.map(body => body.text).join(''), text); + const status = await client.call('command.status', { command_id: command.commandId }); + const duplicate = await client.submit('submit', { text }, { rootId, commandId: command.commandId }).result(deadline()); + assert.equal(duplicate.ingress_seq, accepted.ingress_seq); + const conflict = await errorOf(() => client.submit('submit', { text: 'changed' }, { rootId, commandId: command.commandId }).accepted(deadline())); + const missing = await errorOf(() => client.call('command.status', { command_id: 'absent' })); + const futureCursor = await errorOf(() => client.call('events.replay', { root_id: rootId, cursor: String(BigInt(replay.latest) + 1n), limit: 10 })); + const snapshot = await client.session(rootId).snapshot(); + const history = await client.session(rootId).history.page(); + const transcript = plain({ initialization: { runtime_id, connection_id, protocol_major, protocol_minor, capabilities, negotiated_capabilities, operations, limits, execution_engines, default_execution_engine }, configuration, updated, configurationConflict, provider, unknownProvider, + initial, status, duplicate, conflict, missing, futureCursor, snapshot, history, replay, live, bodies, acceptedIdentity: { command_id: accepted.command_id, ingress_seq: accepted.ingress_seq } }); + await writeFile(join(directory, 'wire.json'), JSON.stringify(wire, null, 2)); + return normalize(transcript, { directory }); + } finally { await stream?.dispose(); client?.close(); await fixture.close(); } +} + +export async function lifecycle(sdk, binary, directory) { + let fixture = await startFixture(binary, directory); + const clients = []; + const open = async transport => { const client = await connect(sdk, fixture, transport, 'lifecycle'); clients.push(client); return client; }; + try { + let client = await open('unix'); + const rootId = await createRoot(client, directory); + const command = client.session(rootId).submit({ text: 'hold:detach' }, { commandId: 'detach' }); + const accepted = await command.accepted(deadline()); + await eventually(async () => (await fixture.effects()).includes('hold:detach'), 'held work starts after acceptance'); + const abort = new AbortController(); + const waiting = command.result({ signal: abort.signal }); abort.abort(); + await assert.rejects(waiting); + assert.equal((await command.status()).status, 'running'); + client.close(); client = await open('websocket'); + assert.equal((await client.call('command.status', { command_id: 'detach' })).ingress_seq, accepted.ingress_seq); + await fixture.release('detach'); + assert.equal((await client.submit('submit', { text: 'hold:detach' }, { rootId, commandId: 'detach' }).result(deadline())).status, 'succeeded'); + const cancel = client.session(rootId).submit({ text: 'hold:cancel' }, { commandId: 'cancelled-work' }); + await cancel.accepted(deadline()); + await eventually(async () => (await fixture.effects()).includes('hold:cancel'), 'cancelled work starts'); + await cancel.cancel().result(deadline()); + assert.equal((await cancel.result(deadline())).status, 'cancelled'); + const held = client.session(rootId).submit({ text: 'hold:crash' }, { commandId: 'crashed-work' }); + const crashAccepted = await held.accepted(deadline()); + await eventually(async () => (await fixture.effects()).includes('hold:crash'), 'crash effect starts'); + const content = await client.upload(new TextEncoder().encode('durable queued attachment'), { rootId, mediaType: 'text/plain' }); + const input = { text: 'queued', attachments: [content.asAttachment('text')] }; + const queued = client.session(rootId).submit(input, { commandId: 'queued-work' }); + assert.equal((await queued.accepted(deadline())).status, 'queued'); + const runtime = fixture.info.runtime_id; + await fixture.close(true); + fixture = await startFixture(binary, directory); + assert.equal(fixture.info.runtime_id, runtime); + for (const transport of ['unix', 'websocket']) { + client = await open(transport); + const recovered = await client.call('command.status', { command_id: 'crashed-work' }); + assert.equal(recovered.status, 'interrupted'); assert.ok(recovered.failure); + assert.equal(recovered.ingress_seq, crashAccepted.ingress_seq); + assert.equal((await client.submit('submit', { text: 'hold:crash' }, { rootId, commandId: 'crashed-work' }).result(deadline())).status, 'interrupted'); + const outcome = await client.session(rootId).submit(input, { commandId: 'queued-work' }).result(deadline()); + assert.equal(outcome.status, 'succeeded'); + assert.equal(JSON.parse(outcome.result.text).parts[0].text, 'durable queued attachment'); + } + const effects = await fixture.effects(); + for (const text of ['hold:detach', 'hold:cancel', 'hold:crash']) assert.equal(effects.filter(value => value === text).length, 1); + assert.equal(effects.filter(value => value.startsWith('{"text":"queued"')).length, 1, 'queued attachment executed more than once'); + } finally { for (const client of clients) client.close(); await fixture.close(); } +} + +async function runCell(client, root, code, child) { + const text = `Compatibility step ${++cellSequence}.\n${cell(code)}`; + const handle = child ? client.session(root).agents.submit(child, text) : client.session(root).submit({ text }); + const result = await handle.result(deadline()); + assert.equal(result.status, 'succeeded', JSON.stringify(result)); + // Submission accepts an inbox entry, not its completed turn. Match this + // unique prompt, then require that turn's own successful tool result. + const inspection = await eventually(async () => { + const value = (await client.session(root).agents.inspect(child ?? root)).result; + const messages = value.page.messages ?? []; + return value.agent.status === 'idle' && messages.some(entry => entry.message?.role === 'user' && entry.message.content === text) && value; + }, 'the submitted turn settles'); + assert.equal(inspection.agent.last_turn.status, 'succeeded', JSON.stringify(inspection.agent.last_turn)); + const messages = inspection.page.messages; + const start = messages.findIndex(entry => entry.message?.role === 'user' && entry.message.content === text); + const turn = messages.slice(start + 1); + assert.ok(!turn.some(entry => entry.message?.role === 'user'), 'another turn followed the submitted prompt'); + const tool = turn.find(entry => entry.message?.role === 'tool' && entry.message.name === 'rlm_exec'); + assert.ok(tool, 'the submitted child turn has no cell result'); + assert.equal((tool.presentation ?? tool.message.presentation).turn_id, inspection.agent.last_turn.turn_id); + const page = await client.call('trace.page', { root_id: root }); + const spans = page.spans.filter(span => span.turn_id === inspection.agent.last_turn.turn_id && span.agent_id === (child ?? root)); + for (const kind of ['agent', 'llm', 'tool']) assert.ok(spans.some(span => span.kind === kind), `new turn lost ${kind} trace`); + const agent = spans.find(span => span.kind === 'agent'); + const toolSpan = spans.find(span => span.kind === 'tool'); + if (text.length <= 512) assert.equal(agent.attrs.input, text); + assert.equal(toolSpan.parent_id, agent.id); + for (const span of spans) { + assert.ok(BigInt(span.end_ns) >= BigInt(span.start_ns) && BigInt(span.start_ns) > 0n); + if (span.kind === 'llm') { assert.equal(span.parent_id, agent.id); assert.equal(span.attrs.provider, 'provider'); assert.equal(span.attrs.model, 'model'); } + } + assert.ok(spans.some(span => span.kind === 'llm' && span.attrs.model_call_id === toolSpan.attrs.emitting_call_id), 'tool lost its emitting model call'); + for (const name of new Set([...code.matchAll(/\b(state\.[a-z_]+|agents\.spawn)\(/g)].map(match => match[1]))) { + const host = spans.find(span => span.kind === 'host' && span.name === name); + assert.ok(host, `new turn lost ${name} host trace`); + assert.equal(host.parent_id, toolSpan.id); + } + return JSON.parse(tool.message.content).output ?? ''; +} + +function inspectStore(directory, ids) { + const database = new DatabaseSync(join(directory, 'home/runtime-v2/sessions.db'), { readOnly: true }); + try { + assert.equal(database.prepare('PRAGMA user_version').get().user_version, 21); + assert.equal(database.prepare('SELECT identity FROM runtime_schema').get().identity, 'whip-recursive-runtime-v21'); + assert.equal(database.prepare('PRAGMA integrity_check').get().integrity_check, 'ok'); + const checkpoints = database.prepare('SELECT root_id,agent_id,envelope,image,bytes FROM agent_checkpoints ORDER BY root_id,agent_id').all(); + for (const id of ids) assert.ok(checkpoints.some(row => row.agent_id === id), `missing checkpoint for ${id}`); + for (const row of checkpoints) { + const envelope = JSON.parse(Buffer.from(row.envelope)); + assert.equal(envelope.sha256, hash(row.image)); assert.equal(envelope.bytes, row.image.length); assert.equal(row.bytes, row.image.length); + } + return { schema: database.prepare('SELECT type,name,tbl_name,sql FROM sqlite_schema ORDER BY type,name').all(), checkpoints: checkpoints.map(row => ({ root: row.root_id, agent: row.agent_id, envelope: hash(row.envelope), image: hash(row.image) })), objects: database.prepare('SELECT digest,size FROM content_objects ORDER BY digest').all() }; + } finally { database.close(); } +} + +async function checkObjects(directory, objects) { + for (const object of objects) { + const bytes = await readFile(join(directory, 'home/runtime-v2/artifacts/sha256', object.digest)); + assert.equal(hash(bytes), object.digest); assert.equal(bytes.length, object.size); + } +} + +async function trace(client, root) { + const page = await client.call('trace.page', { root_id: root }); + assert.ok(page.spans.some(span => span.kind === 'agent')); + for (const kind of ['llm', 'tool', 'host']) assert.ok(page.spans.some(span => span.kind === kind), `missing ${kind} spans`); + const ids = new Set(page.spans.map(span => span.id)); + for (const span of page.spans) { + assert.ok(BigInt(span.end_ns) >= BigInt(span.start_ns) && BigInt(span.start_ns) > 0n, `open/invalid span ${span.id}`); + if (span.parent_id) assert.ok(ids.has(span.parent_id), `broken span parent ${span.id}`); + } + const exported = await client.call('trace.export', { root_id: root }); + const document = await client.content(exported.content, { rootId: root }).readJSON({ maxBytes: 8 << 20 }); + assert.equal(exported.spans, page.spans.length); + assert.ok(document.resourceSpans?.length > 0); + return { page, document }; +} + +export async function rollback(sdk, baseline, candidate, directory) { + await mkdir(directory, { recursive: true }); + const workspace = join(directory, 'workspace'); await mkdir(workspace); + const seed = join(directory, 'seed'), upgraded = join(directory, 'candidate'); + let fixture = await startFixture(baseline, seed, { agents: true }); + const roots = []; + let client; + try { + client = await connect(sdk, fixture, 'unix', 'rollback'); + for (const engine of ['starlark', 'quickjs']) { + const root = await createRoot(client, workspace, engine, `create-${engine}`); + await client.session(root).setPermissionMode(false).result(deadline()); + const code = engine === 'starlark' ? 'memo = 41\ndef increment():\n return memo + 1\nstate.private_set(key="phase", value="base")' : 'var memo = 41; var increment = () => memo + 1; await state.private_set({key:"phase",value:"base"});'; + await runCell(client, root, code); + const prompt = cell(engine === 'starlark' ? 'child_memo = 71\ndef child_value():\n return child_memo + 1' : 'var child_memo = 71; var child_value = () => child_memo + 1;'); + const spawn = engine === 'starlark' ? `agents.spawn(name="keeper", prompt=${JSON.stringify(prompt)}, report="message")` : `await agents.spawn({name:"keeper",prompt:${JSON.stringify(prompt)},report:"message"});`; + await runCell(client, root, spawn); + const listed = await client.session(root).agents.list(); + const agents = Array.isArray(listed.result) ? listed.result : listed.result.agents; + const child = agents.find(agent => agent.name === 'keeper').id; + await runCell(client, root, engine === 'starlark' ? 'print(child_value())' : 'print(child_value());', child); + const content = await client.upload(new TextEncoder().encode('rollback content '.repeat(25_000)), { rootId: root, mediaType: 'text/plain' }); + const expectedTrace = await trace(client, root); + roots.push({ root, child, engine, content: content.handle, expectedTrace }); + await writeFile(join(directory, `trace-${engine}.json`), JSON.stringify(expectedTrace, null, 2)); + } + client.close(); await fixture.close(); + const original = inspectStore(seed, roots.flatMap(value => [value.root, value.child])); + await checkObjects(seed, original.objects); + await cp(seed, upgraded, { recursive: true }); + assert.deepEqual(inspectStore(upgraded, []).checkpoints, original.checkpoints, 'copy lost checkpoints'); + fixture = await startFixture(candidate, upgraded, { agents: true }); + for (const phase of ['candidate', 'rollback']) { + client = await connect(sdk, fixture, phase === 'candidate' ? 'websocket' : 'unix', 'rollback'); + for (const record of roots) { + const { root, child, engine, content } = record; + const observed = await trace(client, root); + assert.ok(BigInt(observed.page.server_time_ns) > 0n); + assert.deepEqual({ ...observed.page, server_time_ns: 'clock' }, { ...record.expectedTrace.page, server_time_ns: 'clock' }, 'persisted trace changed across binary restart'); + assert.deepEqual(observed.document, record.expectedTrace.document, 'OTLP export changed across binary restart'); + const body = await client.content(content, { rootId: root }).readText({ maxBytes: 1 << 20 }); + assert.equal(body, 'rollback content '.repeat(25_000)); + const rootCode = engine === 'starlark' ? 'state.private_get(key=\"phase\")\nprint(increment())' : 'await state.private_get({key:\"phase\"}); print(increment());'; + assert.equal(await runCell(client, root, rootCode), '42\n'); + assert.equal(await runCell(client, root, engine === 'starlark' ? 'print(child_value())' : 'print(child_value());', child), '72\n'); + if (phase === 'candidate') { + await runCell(client, root, engine === 'starlark' ? 'new_memo = 99\nstate.private_set(key=\"phase\", value=\"candidate\")' : 'var new_memo = 99; await state.private_set({key:\"phase\",value:\"candidate\"});'); + await runCell(client, root, engine === 'starlark' ? 'child_new = 199\nstate.private_set(key=\"phase\", value=\"candidate\")' : 'var child_new = 199; await state.private_set({key:\"phase\",value:\"candidate\"});', child); + } else { + assert.equal(await runCell(client, root, engine === 'starlark' ? 'print(new_memo)' : 'print(new_memo);'), '99\n'); + assert.equal(await runCell(client, root, engine === 'starlark' ? 'print(child_new)' : 'print(child_new);', child), '199\n'); + } + record.expectedTrace = await trace(client, root); + } + client.close(); await fixture.close(); + const persisted = inspectStore(upgraded, roots.flatMap(value => [value.root, value.child])); + assert.deepEqual(persisted.schema, original.schema, 'candidate changed schema'); + await checkObjects(upgraded, persisted.objects); + if (phase === 'candidate') fixture = await startFixture(baseline, upgraded, { agents: true }); + } + await writeFile(join(directory, 'rollback.json'), JSON.stringify({ roots, original, final: inspectStore(upgraded, []) }, null, 2)); + } finally { client?.close(); await fixture.close(); } +} From 8f0230444eb447e87c619d7c689eca811ac5d1f3 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Tue, 29 Sep 2026 23:58:34 -0700 Subject: [PATCH 28/67] test: require compatibility in workflow policy checks --- scripts/test-publish-whipcode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-publish-whipcode.py b/scripts/test-publish-whipcode.py index 1e0416ba2..6089ec22d 100644 --- a/scripts/test-publish-whipcode.py +++ b/scripts/test-publish-whipcode.py @@ -577,7 +577,7 @@ def test_shared_gates_still_fail_closed(self): self.assertIn(" pull_request:\n branches: [main, development, 'codex/backend-reorg-*']\n", workflow) self.assertIn(' push:\n branches: [main, development]\n', workflow) self.assertNotIn('continue-on-error:', workflow) - for name in ['lint', 'test', 'build', 'runtime', 'driver', 'sdk', 'distribution', 'desktop', 'mobile']: + for name in ['lint', 'test', 'build', 'runtime', 'driver', 'sdk', 'distribution', 'desktop', 'mobile', 'compatibility']: self.assertIn('${{ needs.' + name + '.result }}" = success', self.job(self.ci, 'go')) self.assertIn('if: always()', self.job(self.ci, 'go')) self.assertNotIn('contents: write', self.security) From bfd030fb7bee920982c8d0ab9f6a4820be962166 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:09:47 -0700 Subject: [PATCH 29/67] refactor(daemon): separate host MCP import ownership --- docs/backend-reorganization-plan.md | 33 ++++++-- internal/daemon/mcp_import_service.go | 16 +++- internal/daemon/mcp_import_service_test.go | 99 +++++++++++++++++++--- internal/daemon/provider_rpc.go | 6 +- internal/daemon/provider_service.go | 3 - internal/daemon/server.go | 2 + 6 files changed, 132 insertions(+), 27 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 4d8b8cb32..3c27bf682 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -638,15 +638,34 @@ Primary implementation references at the recorded revision: Research included local source/dependency inspection, language-server reference mapping, the previous redesign plan and selected GitHub PRs, and current -development CI logs. Full baseline acceptance remains a prerequisite; this -document does not claim it has passed. +development CI logs. At research time, full baseline acceptance remained a +prerequisite. The execution ledger below records subsequent repairs and results. ## Execution ledger +All PRs remain unmerged. Rebased dependency heads are recorded below; successful +checks on an earlier head are not a claim that a current-head rerun has finished. + | Step | Revision and PR | Evidence and status | | --- | --- | --- | -| Dependency-audit prerequisite | [`db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`](https://github.com/context-labs/whip/commit/db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d), [PR #299](https://github.com/context-labs/whip/pull/299) | Only `package-lock.json` changed: 11 `brace-expansion` patch-version entries. Local `npm ci`, production audit at the unchanged high threshold, protocol generation/freshness, all 470 SDK unit tests, client-example build, and packaged SDK smoke passed. Audit reports zero high/critical findings and 15 moderate findings. [Full CI run 36678816413](https://github.com/context-labs/whip/actions/runs/36678816413) is in progress; this is not yet a green execution baseline. | -| Stacked-base CI prerequisite | This PR, based on PR #299. | Extend only the `ci.yml` and `security.yml` pull-request base filters to `codex/backend-reorg-*`. Preserve all existing jobs, the aggregate gate, 90% coverage floor, audit threshold, security scans, and push/schedule/release/publish triggers. Validate the workflow and confirm GitHub starts the full workflow for this non-development-base PR. | - -The prerequisite PRs remain unmerged. Full hosted acceptance and the fixed-client -guardrails must be established before production-code restructuring. +| Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | +| Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Current CI](https://github.com/context-labs/whip/actions/runs/36681079742) is running; current security passed. | +| Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Current CI](https://github.com/context-labs/whip/actions/runs/36681286958) is running; current security passed. | +| Frozen-contract gate | `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [PR #302](https://github.com/context-labs/whip/pull/302) | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine data rollback. Hosted compatibility passed on Linux/macOS before the final workflow-policy assertion update. [Current full CI](https://github.com/context-labs/whip/actions/runs/36681287828) is running; current security passed. | +| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Current CI](https://github.com/context-labs/whip/actions/runs/36681287194) is running; current security passed. | +| Host MCP ownership (plan PR 2) | This change, based on PR #303. | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. | + +### Host MCP ownership and lifetime + +| Concern | Preserved behavior after extraction | +| --- | --- | +| Construction and owner | `NewServer` creates one `hostMCPService` after selecting its provider; `Server` owns the component. The production composition has one server per daemon/provider. | +| Borrowers | The three existing host MCP RPC cases call the component directly with the same protocol values. No forwarding methods remain on `ProviderService`. | +| Cancellation | The component borrows the exact selected provider context. Supplied providers retain their independent lifetime; server or connection cancellation does not replace it. `ProviderService.Close` still cancels icon requests at the existing shutdown point. | +| Lazy resources and sharing | The first enabled icon lookup creates one resolver through the existing `sync.Once`. Cache location, timeout, in-flight sharing and disk cache behavior remain unchanged. Imports do not construct or launch MCP servers. | +| Close and failure cleanup | The component has no independent close action or goroutine. Server shutdown order is unchanged, including provider close before worker join. Construction allocates no resolver, so there is no new partial-construction cleanup. | +| Persistent and session state | Host imports retain the existing single versioned config update, validation and idempotence. Session MCP lifecycle, provider configuration updates, protocol and schema remain unchanged. | + +This step removes host import and icon implementation ownership from provider +onboarding. Provider context borrowing is intentional until a later separately +reviewed composition change can preserve the same cancellation boundary. diff --git a/internal/daemon/mcp_import_service.go b/internal/daemon/mcp_import_service.go index 48ba01d4b..223a141b3 100644 --- a/internal/daemon/mcp_import_service.go +++ b/internal/daemon/mcp_import_service.go @@ -6,6 +6,7 @@ import ( "maps" "path/filepath" "slices" + "sync" "time" "github.com/context-labs/whip/internal/brandicon" @@ -18,9 +19,18 @@ import ( // configuration service rather than among the session-scoped mcp.* actions // because the New session screen has a host but no session yet. +// hostMCPService owns host import operations and the lazy icon resolver. Its +// context is borrowed from provider onboarding so shutdown cancels icon work +// at the same point as before; it does not own a separate cancel function. +type hostMCPService struct { + ctx context.Context + iconsOnce sync.Once + icons *brandicon.Resolver +} + // MCPImportCandidates lists the servers other agents configured on this // host. It reads files only: no candidate is dialed or launched. -func (s *ProviderService) MCPImportCandidates(p protocol.MCPImportCandidatesParams) (protocol.MCPImportCandidatesResult, error) { +func (s *hostMCPService) MCPImportCandidates(p protocol.MCPImportCandidatesParams) (protocol.MCPImportCandidatesResult, error) { if err := validateImportCWD(p.CWD); err != nil { return protocol.MCPImportCandidatesResult{}, err } @@ -52,7 +62,7 @@ func (s *ProviderService) MCPImportCandidates(p protocol.MCPImportCandidatesPara // and records that the offer was answered. A name no source defines fails // the whole call before anything is written; names that cannot be imported // (already native, unsupported) come back in Skipped. -func (s *ProviderService) MCPImportApply(p protocol.MCPImportApplyParams) (protocol.MCPImportApplyResult, error) { +func (s *hostMCPService) MCPImportApply(p protocol.MCPImportApplyParams) (protocol.MCPImportApplyResult, error) { if err := validateImportCWD(p.CWD); err != nil { return protocol.MCPImportApplyResult{}, err } @@ -84,7 +94,7 @@ func (s *ProviderService) MCPImportApply(p protocol.MCPImportApplyParams) (proto // has no bundled mark for. It answers nothing when brandIcons is off in the // host config; otherwise DuckDuckGo's icon endpoint is the one party asked, // once per domain per month thanks to the resolver's on-disk cache. -func (s *ProviderService) MCPBrandIcons(p protocol.MCPBrandIconsParams) (protocol.MCPBrandIconsResult, error) { +func (s *hostMCPService) MCPBrandIcons(p protocol.MCPBrandIconsParams) (protocol.MCPBrandIconsResult, error) { result := protocol.MCPBrandIconsResult{Icons: map[string]string{}} if len(p.Keys) > 64 { return result, errors.New("too many keys") diff --git a/internal/daemon/mcp_import_service_test.go b/internal/daemon/mcp_import_service_test.go index 5c3ece9a6..a9fe7ed4a 100644 --- a/internal/daemon/mcp_import_service_test.go +++ b/internal/daemon/mcp_import_service_test.go @@ -2,6 +2,8 @@ package daemon import ( "bytes" + "context" + "encoding/json" "image" "image/png" "net/http" @@ -11,19 +13,22 @@ import ( "strings" "sync/atomic" "testing" + "time" "github.com/context-labs/whip/internal/brandicon" "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" ) // mcpImportFixture isolates WHIPCODE_HOME with a healthy config that already // owns "ahrefs", points discovery at a Codex file with three servers and an -// empty OpenCode slot, and returns the service plus a project directory. The +// empty OpenCode slot, and returns both host services plus a project directory. The // state rules themselves are pinned in internal/mcp; these tests cover what // the service adds on top. -func mcpImportFixture(t *testing.T) (*ProviderService, string) { +func mcpImportFixture(t *testing.T) (*hostMCPService, *ProviderService, string) { t.Helper() home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) @@ -52,11 +57,11 @@ func mcpImportFixture(t *testing.T) (*ProviderService, string) { t.Cleanup(func() { mcp.CodexPath, mcp.ClaudeGlobalPath, mcp.OpenCodePaths = origC, origG, origOC }) service := NewProviderService(t.Context(), "mcp-import") t.Cleanup(service.Close) - return service, project + return &hostMCPService{ctx: service.ctx}, service, project } func TestMCPImportCandidatesReportOfferPathAndUnreadableSources(t *testing.T) { - service, project := mcpImportFixture(t) + service, _, project := mcpImportFixture(t) result, err := service.MCPImportCandidates(protocol.MCPImportCandidatesParams{CWD: project}) if err != nil { t.Fatal(err) @@ -91,7 +96,7 @@ func TestMCPImportCandidatesReportOfferPathAndUnreadableSources(t *testing.T) { } func TestMCPImportApplyWritesNativeEntriesAndRecordsTheOffer(t *testing.T) { - service, project := mcpImportFixture(t) + service, providers, project := mcpImportFixture(t) result, err := service.MCPImportApply(protocol.MCPImportApplyParams{CWD: project, Names: []string{"paper", "ahrefs"}}) if err != nil { t.Fatal(err) @@ -121,13 +126,13 @@ func TestMCPImportApplyWritesNativeEntriesAndRecordsTheOffer(t *testing.T) { t.Errorf("paper should be native after import, got %s", c.State) } } - if snapshot, err := service.ReadConfiguration(); err != nil || !snapshot.MCPImportOffered { + if snapshot, err := providers.ReadConfiguration(); err != nil || !snapshot.MCPImportOffered { t.Errorf("config.get must report the answered offer, got %+v %v", snapshot.MCPImportOffered, err) } } func TestMCPBrandIconsHonourTheHostSwitch(t *testing.T) { - service, _ := mcpImportFixture(t) + service, providers, _ := mcpImportFixture(t) var hits atomic.Int32 var img bytes.Buffer if err := png.Encode(&img, image.NewRGBA(image.Rect(0, 0, 1, 1))); err != nil { @@ -147,19 +152,19 @@ func TestMCPBrandIconsHonourTheHostSwitch(t *testing.T) { if entries, _ := os.ReadDir(filepath.Join(os.Getenv("WHIPCODE_HOME"), "icons")); len(entries) != 1 { t.Errorf("the cache lives under WHIPCODE_HOME/icons, found %d entries", len(entries)) } - snapshot, err := service.ReadConfiguration() + snapshot, err := providers.ReadConfiguration() if err != nil || !snapshot.BrandIcons { t.Fatalf("config.get must report the default as on: %+v %v", snapshot.BrandIcons, err) } // Off: nothing answered, nothing dialed, and config.get says so. off := false - if _, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: snapshot.Revision, BrandIcons: &off}); err != nil { + if _, err := providers.UpdateConfiguration(ConfigurationUpdate{Revision: snapshot.Revision, BrandIcons: &off}); err != nil { t.Fatal(err) } if got, err = service.MCPBrandIcons(protocol.MCPBrandIconsParams{Keys: []string{"figma.com"}}); err != nil || len(got.Icons) != 0 || hits.Load() != 1 { t.Fatalf("off must answer nothing and dial nothing: %v %v hits %d", got.Icons, err, hits.Load()) } - if snapshot, err = service.ReadConfiguration(); err != nil || snapshot.BrandIcons { + if snapshot, err = providers.ReadConfiguration(); err != nil || snapshot.BrandIcons { t.Fatalf("config.get must report off: %+v %v", snapshot.BrandIcons, err) } if _, err := service.MCPBrandIcons(protocol.MCPBrandIconsParams{Keys: make([]string, 65)}); err == nil { @@ -168,7 +173,7 @@ func TestMCPBrandIconsHonourTheHostSwitch(t *testing.T) { } func TestMCPImportApplyValidatesBeforeWritingAndSkipsQuietly(t *testing.T) { - service, project := mcpImportFixture(t) + service, _, project := mcpImportFixture(t) if _, err := service.MCPImportApply(protocol.MCPImportApplyParams{CWD: project, Names: []string{"paper", "ghost"}}); err == nil || !strings.Contains(err.Error(), "ghost") { t.Fatalf("unknown name should fail the call, got %v", err) } @@ -200,3 +205,75 @@ func TestMCPImportApplyValidatesBeforeWritingAndSkipsQuietly(t *testing.T) { t.Errorf("an unchanged apply must not rewrite config.json (%v)", err) } } + +func TestMCPBrandIconsFollowSuppliedProviderLifetime(t *testing.T) { + _, providers, _ := mcpImportFixture(t) + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + }, providers) + if err != nil { + t.Fatal(err) + } + server, err := NewServer(owner, ServerOptions{}) + if err != nil { + _ = owner.Close() + t.Fatal(err) + } + + started := make(chan struct{}) + cancelled := make(chan struct{}) + endpoint := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, request *http.Request) { + close(started) + <-request.Context().Done() + close(cancelled) + })) + t.Cleanup(endpoint.Close) + t.Cleanup(func() { _ = server.Close() }) + old := brandicon.Endpoint + brandicon.Endpoint = endpoint.URL + "/%s.ico" + t.Cleanup(func() { brandicon.Endpoint = old }) + + // A supplied provider has its own lifetime: server/connection cancellation + // must not end icon resolution before that provider is closed. + server.cancel() + done := make(chan struct{}) + go func() { + defer close(done) + result, rpcErr, handled := server.handleProvider(&serverConn{ctx: server.ctx}, rpcMessage{ + Method: "mcp.brand.icons", Params: json.RawMessage(`{"keys":["example.com"]}`), + }) + if !handled || rpcErr != nil { + t.Errorf("icon response = %v, handled=%t", rpcErr, handled) + return + } + icons, ok := result.(protocol.MCPBrandIconsResult) + if !ok || len(icons.Icons) != 0 { + t.Errorf("cancelled icon result = %#v", result) + } + }() + t.Cleanup(func() { + providers.Close() + select { + case <-done: + case <-time.After(10 * time.Second): + t.Error("icon RPC outlived cleanup") + } + }) + select { + case <-started: + case <-time.After(2 * time.Second): + t.Fatal("server cancellation prevented icon request under the live provider") + } + providers.Close() + select { + case <-cancelled: + case <-time.After(2 * time.Second): + t.Fatal("provider shutdown did not cancel the icon request") + } + select { + case <-done: + case <-time.After(2 * time.Second): + t.Fatal("icon RPC did not settle after provider shutdown") + } +} diff --git a/internal/daemon/provider_rpc.go b/internal/daemon/provider_rpc.go index 7d0b22310..3abf324ae 100644 --- a/internal/daemon/provider_rpc.go +++ b/internal/daemon/provider_rpc.go @@ -85,17 +85,17 @@ func (s *Server) handleProvider(connection *serverConn, request rpcMessage) (any case "mcp.import.candidates": var p protocol.MCPImportCandidatesParams if err = decodeProviderParams(request.Params, &p); err == nil { - result, err = s.providers.MCPImportCandidates(p) + result, err = s.hostMCP.MCPImportCandidates(p) } case "mcp.import.apply": var p protocol.MCPImportApplyParams if err = decodeProviderParams(request.Params, &p); err == nil { - result, err = s.providers.MCPImportApply(p) + result, err = s.hostMCP.MCPImportApply(p) } case "mcp.brand.icons": var p protocol.MCPBrandIconsParams if err = decodeProviderParams(request.Params, &p); err == nil { - result, err = s.providers.MCPBrandIcons(p) + result, err = s.hostMCP.MCPBrandIcons(p) } case "provider.key.set": var p ProviderKeySetup diff --git a/internal/daemon/provider_service.go b/internal/daemon/provider_service.go index 25aa162e8..1a1bb57bc 100644 --- a/internal/daemon/provider_service.go +++ b/internal/daemon/provider_service.go @@ -11,7 +11,6 @@ import ( "sync" "time" - "github.com/context-labs/whip/internal/brandicon" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/llm" @@ -59,8 +58,6 @@ type ProviderService struct { generation string mu sync.Mutex flows map[string]*providerLoginFlow - iconsOnce sync.Once - icons *brandicon.Resolver // created by the first mcp.brand.icons call wg sync.WaitGroup login func(context.Context, func(string, string)) (providerLoginIdentity, error) projects func(context.Context, string, inferencenet.Team) ([]inferencenet.Project, error) diff --git a/internal/daemon/server.go b/internal/daemon/server.go index a4a3b3af0..73fda89be 100644 --- a/internal/daemon/server.go +++ b/internal/daemon/server.go @@ -47,6 +47,7 @@ type ServerOptions struct { type Server struct { providers *ProviderService + hostMCP *hostMCPService daemon *Daemon options ServerOptions ctx context.Context @@ -130,6 +131,7 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { server := &Server{ daemon: value, options: options, ctx: ctx, cancel: cancel, runtimeID: runtimeID, providers: providers, clients: make(map[*serverConn]struct{}), slots: make(chan struct{}, options.MaxConnections), + hostMCP: &hostMCPService{ctx: providers.ctx}, uploads: newUploadManager(value.store, options.RuntimeDir), gatewayStatus: protocol.GatewayStatus{State: "disabled"}, } From fec68225b2e6e888f138d2721c30d827987add73 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:21:10 -0700 Subject: [PATCH 30/67] refactor(daemon): prepare provider operation boundary --- docs/backend-reorganization-plan.md | 54 ++++++++++++-- internal/config/effort.go | 32 +++++++- internal/daemon/budget.go | 2 +- internal/daemon/client_control.go | 95 +----------------------- internal/daemon/control.go | 12 +-- internal/daemon/provider_catalog.go | 72 ++++++++++++++++++ internal/daemon/provider_catalog_test.go | 87 ++++++++++++++++++++++ internal/daemon/provider_list.go | 3 +- internal/daemon/provider_service.go | 19 +++-- internal/daemon/server.go | 2 +- internal/session/permission_mode.go | 8 ++ 11 files changed, 266 insertions(+), 120 deletions(-) create mode 100644 internal/daemon/provider_catalog_test.go diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 3c27bf682..b6f248ebd 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -332,7 +332,7 @@ splitting the struct must not extend its lifetime or change concurrent access. remain unchanged in meaning. Provider operations no longer own MCP import implementation. One authoritative component still owns icon state. -### PRs 3a–3b — Prepare and move the provider boundary +### PRs 3a–3b2 — Prepare and move the provider boundary **PR 3a:** consolidate provider operations currently implemented from `client_control.go`, `query.go`, and `budget.go` into a small callable service @@ -345,7 +345,13 @@ configuration reloads, admission order, and error handling. Locate shared effort/default helpers through references rather than copying them. Preserve the single versioned configuration update and its provisioning-lock scope. -**PR 3b:** move `ProviderService` and its provider implementation files to +**PR 3b1:** prepare integration-test boundaries using existing HTTP/authentication +seams and public service operations. Retain every scenario and assertion; keep +service-private tests with the implementation they exercise. Do not add +production test hooks or interfaces. Review this test-only preparation before +the package move so fixture changes cannot hide an extraction regression. + +**PR 3b2:** move `ProviderService` and its provider implementation files to `internal/provider`. Keep provider RPC decoding/dispatch in the server and client RPC methods with the client. Pass the same protocol/configuration values directly. Preserve the existing separation from `llm` request encoders. @@ -360,7 +366,7 @@ while moving helper functions. **Acceptance:** the new package has no import of `daemon`; there is one provider service implementation; provider configuration/auth/catalog tests, fixed-SDK settings flows, and captured provider request comparisons pass. No encoder, -retry, default, or prompt changes. Review 3a before starting 3b, then review this +retry, default, or prompt changes. Review each preparation PR before starting its successor, then review this stopping point before proceeding. ### PR 4 — Make startup and construction responsibilities readable @@ -526,7 +532,7 @@ already reviewed dependencies. | Merge checkpoint | Group | Evidence required before merging the group | | --- | --- | --- | | Baseline and guardrails | Separate prerequisite repairs/CI setup, then PR 1 (split into sequential PRs if needed). | Full baseline is green; stacked-base CI and frozen-client checks work. Land prerequisite repairs before establishing their dependent baseline. | -| Provider boundary | PRs 2, 3a, and 3b. | Host MCP and provider responsibilities are separated; configuration atomicity, provider semantics, and unchanged clients are verified. | +| Provider boundary | PRs 2, 3a, 3b1, and 3b2. | Host MCP and provider responsibilities are separated; configuration atomicity, provider semantics, and unchanged clients are verified. | | Resource ownership | PRs 4, 5, and 6. | Startup, process ownership, and workspace ownership are explicit; lifecycle, authority, and data compatibility evidence passes. | | Native Go client | PRs 7 and 8. | Client/server dependency is separated; Go clients, unchanged TypeScript SDK, reconnect, and cancellation acceptance passes. | | Selected follow-ups | Each separately agreed actor, tracing, persistence, or cleanup change, or a small group defined before work starts. | The specific benefit is demonstrated and the same compatibility gates pass. No open-ended final stack. | @@ -649,11 +655,12 @@ checks on an earlier head are not a claim that a current-head rerun has finished | Step | Revision and PR | Evidence and status | | --- | --- | --- | | Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | -| Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Current CI](https://github.com/context-labs/whip/actions/runs/36681079742) is running; current security passed. | +| Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | | Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Current CI](https://github.com/context-labs/whip/actions/runs/36681286958) is running; current security passed. | -| Frozen-contract gate | `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [PR #302](https://github.com/context-labs/whip/pull/302) | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine data rollback. Hosted compatibility passed on Linux/macOS before the final workflow-policy assertion update. [Current full CI](https://github.com/context-labs/whip/actions/runs/36681287828) is running; current security passed. | -| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Current CI](https://github.com/context-labs/whip/actions/runs/36681287194) is running; current security passed. | -| Host MCP ownership (plan PR 2) | This change, based on PR #303. | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. | +| Frozen-contract gate | `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [PR #302](https://github.com/context-labs/whip/pull/302) | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine data rollback. [Current full CI](https://github.com/context-labs/whip/actions/runs/36681287828) completed: both Linux/macOS compatibility jobs, Go tests with the 90% coverage floor, lint and runtime checks passed. The aggregate failed the independently reproduced UI scroll-readiness race repaired downstream in PR #303; current security passed. | +| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Current CI](https://github.com/context-labs/whip/actions/runs/36681287194) passed the complete SDK/UI/browser/product job, both compatibility jobs, Go tests with the 90% coverage floor, lint, runtime, mobile, builds, docs and macOS distribution. Desktop and Linux distribution are still finishing; current security passed. | +| Host MCP ownership (plan PR 2) | `d8175212d3db3371b14862dc07ad24fc62393108`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite (250.722s) passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. | +| Provider operation boundary (plan PR 3a) | This change, based on `d8175212d3db3371b14862dc07ad24fc62393108`. | Catalog operation/reload characterization passed three times under the race detector on unchanged production code before extraction. Typed catalog results, compaction validation, model admission and provider-context borrowing now form the narrow operation surface. Shared effort and permission-default helpers move once to their existing configuration/session owners. Validation results are recorded below. | ### Host MCP ownership and lifetime @@ -669,3 +676,34 @@ checks on an earlier head are not a claim that a current-head rerun has finished This step removes host import and icon implementation ownership from provider onboarding. Provider context borrowing is intentional until a later separately reviewed composition change can preserve the same cancellation boundary. + +### Provider operation boundary + +`ProviderService.ListCatalogs` owns the existing catalog read/refresh operation +and returns `protocol.ProviderCatalogsResult` directly. The daemon retains JSON +serialization, query decoding and the query-only 30-second deadline; per-provider +five-second fetches and the final configuration reload are unchanged. The new +blocked-fetch characterization proves that a concurrent configuration change is +reflected in the complete returned result and cannot republish a disabled route. + +`ConfigureCompaction` and `CheckModelProvider` are the existing operations with +exported names. Their call sites keep the versioned configuration callback, +provisioning-lock scope, admission check, accounting reservation and tracing in +exactly their previous order. `Context` exposes the existing provider lifetime +for the host MCP borrower without creating or cancelling another context. + +The catalog-to-storage helper stays private with provider implementation. +`config.ValidateConfiguredEffort` now owns the one shared configuration/catalog +validation body; `session.DefaultPermissionMode` owns the one legacy fallback +body beside its existing constants. Callers retain the same error strings, +explicit-off handling and unrecognized-mode fallback. No new type, configuration +write, package, translation layer or runtime construction is introduced. + +Local validation passed: full-module build, vet and whipvet; focused provider and +registry race tests (18.710s); config and session race suites (1.504s and 147.339s); +and the full daemon race/shuffle suite (251.788s). Fresh compatibility comparisons +passed against the fixed SDK reference and immediate base `d8175212d3db3371b14862dc07ad24fc62393108`, +including both transports, mutation rejection, lifecycle and both-engine data +rollback. The compatibility evidence records the tested working diff and binary +and contract hashes; the submitted PR records the commit and hosted CI results. +Existing CI and frozen-contract gates remain required. diff --git a/internal/config/effort.go b/internal/config/effort.go index 3431284de..dd497563e 100644 --- a/internal/config/effort.go +++ b/internal/config/effort.go @@ -1,6 +1,9 @@ package config -import "slices" +import ( + "fmt" + "slices" +) // ResolveEffort turns the effort a session was asked for into the concrete // value it stores: pinned when set (an explicit config or definition choice is @@ -29,3 +32,30 @@ func ResolveEffort(catalogs map[string]Catalog, provider, modelID, pinned string } return "low" } + +// ValidateConfiguredEffort checks an explicit effort against the configured +// route and catalog, retaining known fallback values when they are unavailable. +func ValidateConfiguredEffort(cfg *Config, model, provider, requested string) error { + if requested == "off" { + return nil + } + known := slices.Contains([]string{"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"}, requested) + if cfg != nil { + resolved, _, _, apiID, err := cfg.ResolveRoute(model, provider) + if err == nil { + catalog := LoadCatalogs()[resolved] + if info := catalog.Find(apiID); info != nil && len(info.ReasoningEfforts) > 0 { + if slices.Contains(info.ReasoningEfforts, requested) { + return nil + } + if known { + return fmt.Errorf("%s does not support effort %q", model, requested) + } + } + } + } + if !known { + return fmt.Errorf("unknown effort level %q", requested) + } + return nil +} diff --git a/internal/daemon/budget.go b/internal/daemon/budget.go index 670adf0ff..25c0963f5 100644 --- a/internal/daemon/budget.go +++ b/internal/daemon/budget.go @@ -44,7 +44,7 @@ func (s *Session) beginAgentModelAttempt(ctx context.Context, agentID string, at // Check at admission for roots, descendants, helpers, compaction and retries. // An attempt already admitted keeps its immutable route and may finish. if s.providers != nil { - if err := s.providers.checkModelProvider(attempt.Provider); err != nil { + if err := s.providers.CheckModelProvider(attempt.Provider); err != nil { return llm.ModelPermit{}, err } } diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index 03ca29e7c..47af76224 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -492,7 +492,7 @@ func (s *Session) executeClientCommand(actorCtx context.Context, admission sessi var err error if operation == "compaction.configure" { cfg, _, patchErr := config.UpdateVersioned("", func(cfg *config.Config) error { - return s.providers.configureCompaction(cfg, action.Model, action.Provider) + return s.providers.ConfigureCompaction(cfg, action.Model, action.Provider) }) err = patchErr if err == nil { @@ -1565,32 +1565,7 @@ func validateEffort(model, provider, requested string) error { if err != nil { cfg = nil // Validate known fallback values without an unavailable catalog. } - return validateConfiguredEffort(cfg, model, provider, requested) -} - -func validateConfiguredEffort(cfg *config.Config, model, provider, requested string) error { - if requested == "off" { - return nil - } - known := slices.Contains([]string{"none", "minimal", "low", "medium", "high", "xhigh", "max", "ultra"}, requested) - if cfg != nil { - resolved, _, _, apiID, err := cfg.ResolveRoute(model, provider) - if err == nil { - catalog := config.LoadCatalogs()[resolved] - if info := catalog.Find(apiID); info != nil && len(info.ReasoningEfforts) > 0 { - if slices.Contains(info.ReasoningEfforts, requested) { - return nil - } - if known { - return fmt.Errorf("%s does not support effort %q", model, requested) - } - } - } - } - if !known { - return fmt.Errorf("unknown effort level %q", requested) - } - return nil + return config.ValidateConfiguredEffort(cfg, model, provider, requested) } func compatibleEffort(model, provider, current string) string { @@ -1816,70 +1791,8 @@ func clientProviderCatalogs(ctx context.Context, providers *ProviderService, ref } func clientProviderCatalogsFor(ctx context.Context, providers *ProviderService, refresh bool, selected string) (string, error) { - cfg, err := config.Load() - if err != nil { - return "", err - } - catalogs := providers.CatalogsFor(cfg) - failures := map[string]string{} - for name, provider := range cfg.EffectiveProviders() { - if selected != "" && name != selected { - continue - } - status, err := providers.providerStatus(cfg, name) - if err != nil || (status.AuthState != "unchecked" && (status.Available == nil || !*status.Available)) { - continue - } - if cached, ok := catalogs[name]; !refresh && ok && !cached.NeedsDiscovery() { - continue - } - fetchCtx, cancel := context.WithTimeout(ctx, 5*time.Second) - err = providers.refreshCatalog(fetchCtx, name, provider) - cancel() - if err != nil { - failures[name] = "Model discovery failed; check the provider connection and retry." - } - } - // Account/config changes may have completed while discovery was in flight. - cfg, err = config.Load() - if err != nil { - return "", err - } - result := ProviderCatalogsResult{Catalogs: providers.CatalogsFor(cfg), Models: map[string]protocol.ModelDescriptor{}, Providers: map[string]protocol.ProviderDescriptor{}, Errors: failures} - for name, model := range cfg.Models { - result.Models[name] = protocol.ModelDescriptor{Name: model.Name, ID: model.ID, Providers: model.Providers, Context: model.ContextWindow(), Vision: model.Vision} - for _, provider := range model.Providers { - result.Providers[provider] = protocol.ProviderDescriptor{Available: new(false)} - } - } - for name, provider := range cfg.EffectiveProviders() { - status, err := providers.providerStatus(cfg, name) - available := err == nil && ((status.Available != nil && *status.Available) || status.AuthState == "unchecked") - descriptor := protocol.ProviderDescriptor{Available: new(available)} - if available { - descriptor.BaseURL = provider.BaseURL - } else { - delete(result.Catalogs, name) - } - result.Providers[name] = descriptor - } - return marshalClientOutput(result, nil) -} - -func modelInfoLites(values []llm.ModelInfo) []config.ModelInfoLite { - result := make([]config.ModelInfoLite, 0, len(values)) - for _, value := range values { - var pricing llm.Pricing - if value.Pricing != nil { - pricing = *value.Pricing - } - result = append(result, config.ModelInfoLite{ - ID: value.ID, ContextLength: value.ContextLength, MaxCompletionTokens: value.MaxCompletionTokens, - ReasoningEfforts: value.ReasoningEfforts, InputModalities: value.InputModalities, - Pricing: pricing, - }) - } - return result + result, err := providers.ListCatalogs(ctx, refresh, selected) + return marshalClientOutput(result, err) } func decodeClientAction(raw json.RawMessage, value *clientActionPayload) error { diff --git a/internal/daemon/control.go b/internal/daemon/control.go index 36a48cecf..90c30dafc 100644 --- a/internal/daemon/control.go +++ b/internal/daemon/control.go @@ -399,14 +399,6 @@ func resolveSessionDefaults(ctx context.Context, source DefinitionSource, create return sessionDefaults(create, definition) } -// defaultPermissionMode fails closed for legacy or unrecognized host settings. -func defaultPermissionMode(cfg *config.Config) string { - if cfg.DefaultPermissionMode == session.PermissionModeAutomatic { - return session.PermissionModeAutomatic - } - return session.PermissionModePrompt -} - // sessionDefaults fills omitted routing from the definition's model defaults, // then omitted routing, engine, and permission mode from host configuration. func sessionDefaults(create CreateSession, definition agentdef.Definition) (CreateSession, error) { @@ -427,7 +419,7 @@ func sessionDefaults(create CreateSession, definition agentdef.Definition) (Crea return create, err } if needPermissionMode { - create.PermissionMode = defaultPermissionMode(cfg) + create.PermissionMode = session.DefaultPermissionMode(cfg.DefaultPermissionMode) } if create.ExecutionEngine == "" { create.ExecutionEngine = cfg.RLM.Engine() @@ -447,7 +439,7 @@ func sessionDefaults(create CreateSession, definition agentdef.Definition) (Crea } if needEffort { if create.Effort != "" { - if err := validateConfiguredEffort(cfg, create.Model, create.Provider, create.Effort); err != nil { + if err := config.ValidateConfiguredEffort(cfg, create.Model, create.Provider, create.Effort); err != nil { return create, err } } diff --git a/internal/daemon/provider_catalog.go b/internal/daemon/provider_catalog.go index f09810daa..afb645e98 100644 --- a/internal/daemon/provider_catalog.go +++ b/internal/daemon/provider_catalog.go @@ -1,13 +1,85 @@ package daemon import ( + "context" "time" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" ) func cacheProviderModels(provider, baseURL string, models []llm.ModelInfo) { // Catalogs are a cache; the runtime can refresh a failed write on next use. _ = config.UpdateCatalog(provider, config.Catalog{FetchedAt: time.Now(), BaseURL: baseURL, Models: modelInfoLites(models)}) } + +// ListCatalogs refreshes the requested catalogs and returns the current host +// configuration after discovery. Request decoding and serialization stay with +// the caller. +func (s *ProviderService) ListCatalogs(ctx context.Context, refresh bool, selected string) (protocol.ProviderCatalogsResult, error) { + cfg, err := config.Load() + if err != nil { + return protocol.ProviderCatalogsResult{}, err + } + catalogs := s.CatalogsFor(cfg) + failures := map[string]string{} + for name, provider := range cfg.EffectiveProviders() { + if selected != "" && name != selected { + continue + } + status, err := s.providerStatus(cfg, name) + if err != nil || (status.AuthState != "unchecked" && (status.Available == nil || !*status.Available)) { + continue + } + if cached, ok := catalogs[name]; !refresh && ok && !cached.NeedsDiscovery() { + continue + } + fetchCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + err = s.refreshCatalog(fetchCtx, name, provider) + cancel() + if err != nil { + failures[name] = "Model discovery failed; check the provider connection and retry." + } + } + // Account/config changes may have completed while discovery was in flight. + cfg, err = config.Load() + if err != nil { + return protocol.ProviderCatalogsResult{}, err + } + result := protocol.ProviderCatalogsResult{Catalogs: s.CatalogsFor(cfg), Models: map[string]protocol.ModelDescriptor{}, Providers: map[string]protocol.ProviderDescriptor{}, Errors: failures} + for name, model := range cfg.Models { + result.Models[name] = protocol.ModelDescriptor{Name: model.Name, ID: model.ID, Providers: model.Providers, Context: model.ContextWindow(), Vision: model.Vision} + for _, provider := range model.Providers { + result.Providers[provider] = protocol.ProviderDescriptor{Available: new(false)} + } + } + for name, provider := range cfg.EffectiveProviders() { + status, err := s.providerStatus(cfg, name) + available := err == nil && ((status.Available != nil && *status.Available) || status.AuthState == "unchecked") + descriptor := protocol.ProviderDescriptor{Available: new(available)} + if available { + descriptor.BaseURL = provider.BaseURL + } else { + delete(result.Catalogs, name) + } + result.Providers[name] = descriptor + } + return result, nil +} + +func modelInfoLites(values []llm.ModelInfo) []config.ModelInfoLite { + result := make([]config.ModelInfoLite, 0, len(values)) + for _, value := range values { + var pricing llm.Pricing + if value.Pricing != nil { + pricing = *value.Pricing + } + result = append(result, config.ModelInfoLite{ + ID: value.ID, ContextLength: value.ContextLength, MaxCompletionTokens: value.MaxCompletionTokens, + ReasoningEfforts: value.ReasoningEfforts, InputModalities: value.InputModalities, + Pricing: pricing, + }) + } + return result +} diff --git a/internal/daemon/provider_catalog_test.go b/internal/daemon/provider_catalog_test.go new file mode 100644 index 000000000..c3745efef --- /dev/null +++ b/internal/daemon/provider_catalog_test.go @@ -0,0 +1,87 @@ +package daemon + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "sync" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/protocol" +) + +func TestProviderCatalogQueryReloadsConfigurationAfterDiscovery(t *testing.T) { + service := providerConnectionsFixture(t) + started, release := make(chan struct{}), make(chan struct{}) + var releaseOnce sync.Once + resume := func() { releaseOnce.Do(func() { close(release) }) } + upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + close(started) + select { + case <-release: + _, _ = w.Write([]byte(`{"data":[{"id":"late-model"}]}`)) + case <-r.Context().Done(): + } + })) + t.Cleanup(upstream.Close) + t.Cleanup(resume) + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers = map[string]config.Provider{ + "custom": {BaseURL: upstream.URL, APIKey: "fixture"}, + "other": {BaseURL: "https://other.example/v1", APIKey: "fixture"}, + } + cfg.Models = map[string]config.Model{"old-alias": {ID: "old-model", Providers: []string{"custom"}}} + return nil + }) + if err != nil { + t.Fatal(err) + } + type response struct { + body string + err error + } + done := make(chan response, 1) + go func() { + body, err := queryProviderCatalogs(t.Context(), service, json.RawMessage(`{"provider":"custom","refresh":true}`)) + done <- response{body, err} + }() + select { + case <-started: + case <-time.After(5 * time.Second): + t.Fatal("catalog discovery did not start") + } + _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.DisabledProviders = []string{"custom"} + cfg.Models = map[string]config.Model{"new-alias": {ID: "new-model", Providers: []string{"other"}}} + return nil + }) + resume() + if err != nil { + t.Fatal(err) + } + var received response + select { + case received = <-done: + case <-time.After(5 * time.Second): + t.Fatal("catalog query did not finish") + } + if received.err != nil { + t.Fatal(received.err) + } + var result protocol.ProviderCatalogsResult + if err := json.Unmarshal([]byte(received.body), &result); err != nil { + t.Fatal(err) + } + if len(result.Models) != 1 || result.Models["new-alias"].ID != "new-model" { + t.Fatalf("query retained models from before discovery: %+v", result.Models) + } + other := result.Providers["other"] + if len(result.Providers) != 1 || other.Available == nil || !*other.Available || other.BaseURL != "https://other.example/v1" { + t.Fatalf("query retained providers from before discovery: %+v", result.Providers) + } + if len(result.Catalogs) != 0 || len(result.Errors) != 1 || result.Errors["custom"] != "Model discovery failed; check the provider connection and retry." { + t.Fatalf("late disabled-provider discovery was not rejected: %+v", result) + } +} diff --git a/internal/daemon/provider_list.go b/internal/daemon/provider_list.go index bf6302864..8e4d9209a 100644 --- a/internal/daemon/provider_list.go +++ b/internal/daemon/provider_list.go @@ -202,7 +202,8 @@ func inferenceNetLoginRoute(cfg *config.Config) error { return nil } -func (s *ProviderService) checkModelProvider(name string) error { +// CheckModelProvider verifies the current host connection before model admission. +func (s *ProviderService) CheckModelProvider(name string) error { cfg, err := config.Load() if err != nil { return errors.New("could not read provider configuration on this host") diff --git a/internal/daemon/provider_service.go b/internal/daemon/provider_service.go index 1a1bb57bc..99294bdff 100644 --- a/internal/daemon/provider_service.go +++ b/internal/daemon/provider_service.go @@ -130,6 +130,10 @@ func NewProviderService(ctx context.Context, generation string) *ProviderService return s } +// Context is the provider lifetime borrowed by host components. Close cancels +// it at the existing provider shutdown boundary. +func (s *ProviderService) Context() context.Context { return s.ctx } + func (s *ProviderService) Close() { s.mu.Lock() s.cancel() @@ -162,7 +166,7 @@ func runtimeConfiguration(c *config.Config, revision string) RuntimeConfiguratio return RuntimeConfiguration{ DisabledProviders: &disabled, DefaultExecutionEngine: c.RLM.Engine(), - DefaultPermissionMode: defaultPermissionMode(c), + DefaultPermissionMode: session.DefaultPermissionMode(c.DefaultPermissionMode), RemoteHosts: &hosts, ImportClaude: claude, ImportCodex: codex, MCPImportOffered: c.MCPImport != nil && c.MCPImport.Offered, BrandIcons: c.BrandIcons == nil || *c.BrandIcons, @@ -276,7 +280,7 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon if p.CompactProvider != nil { provider = *p.CompactProvider } - if err := s.configureCompaction(c, model, provider); err != nil { + if err := s.ConfigureCompaction(c, model, provider); err != nil { return err } } @@ -292,7 +296,7 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon // A blank configured default is "not chosen": each new session resolves // its own concrete effort against the model at creation. if p.DefaultEffort != nil && *p.DefaultEffort != "" { - if err := validateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, *p.DefaultEffort); err != nil { + if err := config.ValidateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, *p.DefaultEffort); err != nil { return err } } @@ -301,7 +305,7 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon if !selection.Ready { return errors.New("select a model available on a connected provider before saving defaults") } - if p.DefaultEffort == nil && c.DefaultEffort != "" && validateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, c.DefaultEffort) != nil { + if p.DefaultEffort == nil && c.DefaultEffort != "" && config.ValidateConfiguredEffort(c, c.DefaultModel, c.DefaultProvider, c.DefaultEffort) != nil { c.DefaultEffort = "" } } @@ -318,9 +322,10 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon return runtimeConfiguration(c, revision), nil } -// configureCompaction validates new custom selections without revalidating an -// unchanged saved override when a settings form resends it. -func (s *ProviderService) configureCompaction(c *config.Config, model, provider string) error { +// ConfigureCompaction validates new custom selections without revalidating an +// unchanged saved override when a settings form resends it. The caller owns +// the configuration update transaction and any provisioning lock. +func (s *ProviderService) ConfigureCompaction(c *config.Config, model, provider string) error { if model == "" { c.CompactModel, c.CompactProvider = "", "" return nil diff --git a/internal/daemon/server.go b/internal/daemon/server.go index 73fda89be..8c3df44bd 100644 --- a/internal/daemon/server.go +++ b/internal/daemon/server.go @@ -131,7 +131,7 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { server := &Server{ daemon: value, options: options, ctx: ctx, cancel: cancel, runtimeID: runtimeID, providers: providers, clients: make(map[*serverConn]struct{}), slots: make(chan struct{}, options.MaxConnections), - hostMCP: &hostMCPService{ctx: providers.ctx}, + hostMCP: &hostMCPService{ctx: providers.Context()}, uploads: newUploadManager(value.store, options.RuntimeDir), gatewayStatus: protocol.GatewayStatus{State: "disabled"}, } diff --git a/internal/session/permission_mode.go b/internal/session/permission_mode.go index daffdea03..5071b82a7 100644 --- a/internal/session/permission_mode.go +++ b/internal/session/permission_mode.go @@ -13,6 +13,14 @@ const ( PermissionModeAutomatic = "automatic" ) +// DefaultPermissionMode fails closed for legacy or unrecognized host settings. +func DefaultPermissionMode(configured string) string { + if configured == PermissionModeAutomatic { + return PermissionModeAutomatic + } + return PermissionModePrompt +} + // PermissionMode reads the saved consent choice, including for an unopened root. func (s *Store) PermissionMode(ctx context.Context, rootID string) (string, error) { var mode string From 675717575868c5b3b9bf2da1a9b2863238b12a28 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:31:26 -0700 Subject: [PATCH 31/67] test(daemon): exercise provider setup through public auth boundaries --- docs/backend-reorganization-plan.md | 38 +++- .../daemon/provider_client_behavior_test.go | 53 ++---- .../provider_client_configuration_test.go | 12 +- .../daemon/provider_configuration_test.go | 4 +- internal/daemon/provider_integration_test.go | 170 ++++++++++++++++++ internal/daemon/provider_openai_test.go | 57 ++++-- internal/daemon/subscription_runtime_test.go | 13 +- 7 files changed, 274 insertions(+), 73 deletions(-) create mode 100644 internal/daemon/provider_integration_test.go diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index b6f248ebd..eeb64a539 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -656,11 +656,12 @@ checks on an earlier head are not a claim that a current-head rerun has finished | --- | --- | --- | | Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | | Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | -| Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Current CI](https://github.com/context-labs/whip/actions/runs/36681286958) is running; current security passed. | +| Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681286958) and current security passed. | | Frozen-contract gate | `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [PR #302](https://github.com/context-labs/whip/pull/302) | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine data rollback. [Current full CI](https://github.com/context-labs/whip/actions/runs/36681287828) completed: both Linux/macOS compatibility jobs, Go tests with the 90% coverage floor, lint and runtime checks passed. The aggregate failed the independently reproduced UI scroll-readiness race repaired downstream in PR #303; current security passed. | -| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Current CI](https://github.com/context-labs/whip/actions/runs/36681287194) passed the complete SDK/UI/browser/product job, both compatibility jobs, Go tests with the 90% coverage floor, lint, runtime, mobile, builds, docs and macOS distribution. Desktop and Linux distribution are still finishing; current security passed. | -| Host MCP ownership (plan PR 2) | `d8175212d3db3371b14862dc07ad24fc62393108`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite (250.722s) passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. | -| Provider operation boundary (plan PR 3a) | This change, based on `d8175212d3db3371b14862dc07ad24fc62393108`. | Catalog operation/reload characterization passed three times under the race detector on unchanged production code before extraction. Typed catalog results, compaction validation, model admission and provider-context borrowing now form the narrow operation surface. Shared effort and permission-default helpers move once to their existing configuration/session owners. Validation results are recorded below. | +| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681287194) passed, including SDK/UI/browser/product, both compatibility jobs, Go tests with the 90% coverage floor, lint, runtime, mobile, builds, docs, desktop and distribution. Current security also passed; this is the combined green prerequisite baseline. | +| Host MCP ownership (plan PR 2) | `d8175212d3db3371b14862dc07ad24fc62393108`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite (250.722s) passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. [Full current CI](https://github.com/context-labs/whip/actions/runs/36682214774) and current security passed. | +| Provider operation boundary (plan PR 3a) | `a211fb0e7629f9692eb5133aa00244aea17e38a9`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog operation/reload characterization passed three times under the race detector on unchanged production code before extraction. Typed catalog results, compaction validation, model admission and provider-context borrowing now form the narrow operation surface. Shared effort and permission-default helpers move once to their existing configuration/session owners. Validation results are recorded below. [Current CI](https://github.com/context-labs/whip/actions/runs/36683418233) is running; current security passed. | +| Provider integration test boundary (plan PR 3b1) | This change, based on `a211fb0e7629f9692eb5133aa00244aea17e38a9`. | The five existing affected integration tests now use HTTP/auth persistence rather than private provider callbacks. They passed three times under the race detector (23.256s). Full-module build, vet and whipvet and fresh fixed-SDK compatibility passed. The full daemon race/shuffle suite passed (261.125s). | ### Host MCP ownership and lifetime @@ -707,3 +708,32 @@ including both transports, mutation rejection, lifecycle and both-engine data rollback. The compatibility evidence records the tested working diff and binary and contract hashes; the submitted PR records the commit and hosted CI results. Existing CI and frozen-contract gates remain required. + + +### Provider integration test boundary + +The existing onboarding, custom-connection, host RPC, Unix/WebSocket login and +recursive subscription-runtime tests stay in daemon. Local HTTP fixtures now +exercise model discovery, device authorization, workspace/project selection, +key provisioning and credential persistence through their existing public APIs. +Assertions retain the same token, team and project identities, configuration +conflicts, cancellation/recovery, unsupported rotation, and secret isolation. +A persisted per-project machine key also connects the provisioning request to +its saved identity. Runtime credentials are seeded by a separate public +`openaiauth.Manager` before the provider service reads them. + +The unsigned-account rotation assertion runs before login because successful +login now actually persists credentials. The failed-rotation assertion remains; +no production behavior changes. HTTP overrides are installed before daemon +construction and restored after its workers close. Unexpected external hosts +fail the test, and all fixture data lives in temporary homes. The service-private +unit tests remain in place for the separate package-move PR 3b2. + +Fresh compatibility evidence at `/private/tmp/whip-backend-compat-pr3b1-fresh/evidence.json` +records the immutable SDK reference `271c0f8d2a35648d1b45056d57432590b783483c`, +immediate base `a211fb0e7629f9692eb5133aa00244aea17e38a9`, and the complete staged +test diff, including the new fixture. Node v24.14.1 and Go 1.27.0 on darwin/arm64 +built all three selected integration binaries freshly. SDK and generated +contract artifacts matched; both transport comparisons, deliberate mutation +rejection, lifecycle checks, and both-engine fixed/base → candidate → base data +rollback passed. Production source, SDK, schema and CI requirements are unchanged. diff --git a/internal/daemon/provider_client_behavior_test.go b/internal/daemon/provider_client_behavior_test.go index 6691913b2..f7fd291c1 100644 --- a/internal/daemon/provider_client_behavior_test.go +++ b/internal/daemon/provider_client_behavior_test.go @@ -123,36 +123,12 @@ func TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts(t *tes func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *testing.T) { for _, mode := range []string{"client", "root"} { t.Run(mode, func(t *testing.T) { - server, client, root, rootID := providerBehaviorFixture(t) + providerOnboardingHTTPFixture(t) + _, client, root, rootID := providerBehaviorFixture(t) var api providerBehaviorClient = client if mode == "root" { api = root } - service := server.providers - service.validate = func(_ context.Context, _, key string) ([]llm.ModelInfo, error) { - if key != "private-api-key" { - return nil, errors.New("bad key") - } - return []llm.ModelInfo{ - {ID: "fixture-model", SupportsTools: new(true), OutputModalities: []string{"text"}}, - {ID: "compact-model"}, - }, nil - } - service.login = func(_ context.Context, code func(string, string)) (providerLoginIdentity, error) { - code("https://example.test/verify", "display-code") - return providerLoginIdentity{token: "private-session-token", email: "person@example.test", teams: []inferencenet.Team{{ID: "team", Name: "Team"}, {ID: "other", Name: "Other"}}}, nil - } - service.projects = func(context.Context, string, inferencenet.Team) ([]inferencenet.Project, error) { - return []inferencenet.Project{{ID: "existing", Name: "Existing"}, {ID: "other", Name: "Other"}}, nil - } - service.create = func(_ context.Context, token string, team inferencenet.Team, name string) (inferencenet.Project, error) { - if token != "private-session-token" || team.ID != "team" || name != "Created" { - return inferencenet.Project{}, errors.New("invalid creation identity") - } - return inferencenet.Project{ID: "created", Name: name}, nil - } - finished := make(chan inferencenet.Auth, 2) - service.finish = func(_ context.Context, auth inferencenet.Auth) error { finished <- auth; return nil } before, err := api.ReadConfiguration(t.Context()) if err != nil { t.Fatal(err) @@ -184,16 +160,20 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if err != nil || cfg.Providers["openrouter"].APIKey != "private-api-key" { t.Fatalf("host key not persisted: %v", err) } + // Real login persists credentials, so check unsigned rotation before signing in. + if _, err := api.RotateProviderKey(t.Context(), config.InferenceNetProvider); err == nil { + t.Fatal("unsigned account rotated a key") + } for _, project := range []string{"existing", "created"} { flow, err := api.BeginLogin(t.Context()) if err != nil { t.Fatal(err) } - waitProviderState(t, service, flow.FlowID, "choose_team") + waitProviderClientState(t, api, flow.FlowID, "choose_team") if _, err := api.SelectLoginTeam(t.Context(), flow.FlowID, "team"); err != nil { t.Fatal(err) } - waitProviderState(t, service, flow.FlowID, "choose_project") + waitProviderClientState(t, api, flow.FlowID, "choose_project") if project == "existing" { _, err = api.SelectLoginProject(t.Context(), flow.FlowID, project) } else { @@ -202,18 +182,14 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if err != nil { t.Fatal(err) } - waitProviderState(t, service, flow.FlowID, "succeeded") + waitProviderClientState(t, api, flow.FlowID, "succeeded") result, err := api.LoginStatus(t.Context(), flow.FlowID) if err != nil || result.State != "succeeded" || result.ProjectID != project { t.Fatalf("login=%+v %v", result, err) } - select { - case auth := <-finished: - if auth.ProjectID != project || auth.SessionToken != "private-session-token" { - t.Fatalf("wrong provisioning identity: %+v", auth) - } - case <-time.After(time.Second): - t.Fatal("provisioning did not complete") + auth, err := inferencenet.LoadAuth() + if err != nil || auth.ProjectID != project || auth.SessionToken != "private-session-token" || auth.TeamID != "team" || auth.MachineKey != "private-machine-"+project { + t.Fatalf("wrong persisted provisioning identity: project=%q team=%q error=%v", auth.ProjectID, auth.TeamID, err) } } flow, err := api.BeginLogin(t.Context()) @@ -228,9 +204,6 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if err != nil || len(logins.Flows) != 3 { t.Fatalf("lost login states: %+v %v", logins, err) } - if _, err := api.RotateProviderKey(t.Context(), config.InferenceNetProvider); err == nil { - t.Fatal("unsigned account rotated a key") - } if _, err := api.LogoutProvider(t.Context(), config.InferenceNetProvider); err != nil { t.Fatal(err) } @@ -247,7 +220,7 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes t.Fatal(err) } encoded, _ := json.Marshal([]any{after, status, logins, replay}) - if strings.Contains(string(encoded), "private-api-key") || strings.Contains(string(encoded), "private-session-token") { + if strings.Contains(string(encoded), "private-api-key") || strings.Contains(string(encoded), "private-session-token") || strings.Contains(string(encoded), "private-machine-") { t.Fatal("credentials escaped host storage") } }) diff --git a/internal/daemon/provider_client_configuration_test.go b/internal/daemon/provider_client_configuration_test.go index 58d396ec6..514499059 100644 --- a/internal/daemon/provider_client_configuration_test.go +++ b/internal/daemon/provider_client_configuration_test.go @@ -3,7 +3,6 @@ package daemon import ( "context" "encoding/json" - "errors" "reflect" "slices" "strings" @@ -30,24 +29,19 @@ type providerConfigurationClient interface { func TestProviderClientsCustomConnectionLifecycle(t *testing.T) { for _, mode := range []string{"client", "root"} { t.Run(mode, func(t *testing.T) { - server, client, root, rootID := providerBehaviorFixture(t) + _, client, root, rootID := providerBehaviorFixture(t) var api providerConfigurationClient = client if mode == "root" { api = root } - server.providers.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { - if endpoint != "https://example.test/v1" || key != "private-fixture-key" { - return nil, errors.New("incorrect discovery credentials") - } - return []llm.ModelInfo{{ID: "fixture-chat", SupportsTools: new(true), OutputModalities: []string{"text"}}}, nil - } + endpoint := providerModelEndpoint(t, "private-fixture-key", []llm.ModelInfo{{ID: "fixture-chat", SupportsTools: new(true), OutputModalities: []string{"text"}}}) before, err := api.ReadConfiguration(t.Context()) if err != nil { t.Fatal(err) } created, err := api.CreateProvider(t.Context(), protocol.ProviderCreateParams{ Revision: before.Revision, Provider: "custom-fixture", - Definition: protocol.ProviderDefinition{Name: "Fixture", BaseURL: "https://example.test/v1", API: "openai-completions"}, + Definition: protocol.ProviderDefinition{Name: "Fixture", BaseURL: endpoint, API: "openai-completions"}, Credential: protocol.ProviderCredential{Mode: "api_key", Key: "private-fixture-key"}, }) if err != nil || !created.Custom || created.Discovery == nil || created.Discovery.Status != "loaded" || created.Discovery.ModelCount != 1 { diff --git a/internal/daemon/provider_configuration_test.go b/internal/daemon/provider_configuration_test.go index bdf76a9cf..3f969191e 100644 --- a/internal/daemon/provider_configuration_test.go +++ b/internal/daemon/provider_configuration_test.go @@ -460,12 +460,10 @@ func TestProviderConfigurationLastProviderRemovalPreservesRecoveryGuard(t *testi func TestProviderConfigurationHostRPCAndSecretContracts(t *testing.T) { s := customProviderService(t) - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return []llm.ModelInfo{{ID: "fixture"}}, nil - } server := &Server{providers: s} connection := &serverConn{ctx: t.Context()} p := customProviderParams(t, s) + p.Definition.BaseURL = providerModelEndpoint(t, p.Credential.Key, []llm.ModelInfo{{ID: "fixture"}}) body, _ := json.Marshal(p) result, rpcErr, handled := server.handleProvider(connection, rpcMessage{Method: "provider.create", Params: body}) if rpcErr != nil || !handled { diff --git a/internal/daemon/provider_integration_test.go b/internal/daemon/provider_integration_test.go new file mode 100644 index 000000000..7597cd364 --- /dev/null +++ b/internal/daemon/provider_integration_test.go @@ -0,0 +1,170 @@ +package daemon + +import ( + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "net/http/httptest" + "reflect" + "slices" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/llm" +) + +type providerIntegrationTransport func(*http.Request) (*http.Response, error) + +func (f providerIntegrationTransport) RoundTrip(r *http.Request) (*http.Response, error) { + return f(r) +} + +// Install before constructing the daemon so its workers close before restoring +// the transport. Only the named upstream hosts and local test servers may run. +func providerHTTPFixture(t *testing.T, hosts []string, handler http.HandlerFunc) *httptest.Server { + t.Helper() + endpoint := httptest.NewServer(handler) + previous := http.DefaultTransport + http.DefaultTransport = providerIntegrationTransport(func(r *http.Request) (*http.Response, error) { + if slices.Contains(hosts, r.URL.Hostname()) { + request := r.Clone(r.Context()) + request.URL.Scheme, request.URL.Host = "http", endpoint.Listener.Addr().String() + return previous.RoundTrip(request) + } + if r.URL.Scheme == "http" && net.ParseIP(r.URL.Hostname()).IsLoopback() { + return previous.RoundTrip(r) + } + t.Errorf("unexpected provider fixture request to %s", r.URL.Hostname()) + return nil, fmt.Errorf("unexpected provider fixture request to %s", r.URL.Hostname()) + }) + t.Cleanup(func() { + http.DefaultTransport = previous + endpoint.Close() + }) + return endpoint +} + +func providerModelEndpoint(t *testing.T, key string, models []llm.ModelInfo) string { + t.Helper() + endpoint := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet || r.URL.Path != "/v1/models" || r.Header.Get("Authorization") != "Bearer "+key { + t.Error("incorrect model discovery route or credentials") + http.Error(w, "invalid discovery request", http.StatusUnauthorized) + return + } + _ = json.NewEncoder(w).Encode(map[string]any{"data": models}) + })) + t.Cleanup(endpoint.Close) + return endpoint.URL + "/v1" +} + +func providerOnboardingHTTPFixture(t *testing.T) { + t.Helper() + endpoint := providerHTTPFixture(t, []string{"openrouter.ai"}, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + if strings.HasPrefix(r.URL.Path, "/api/v1/") { + if r.Header.Get("Authorization") != "Bearer private-api-key" { + t.Error("OpenRouter discovery received an untrimmed or incorrect key") + http.Error(w, "bad key", http.StatusUnauthorized) + return + } + } else if !strings.HasPrefix(r.URL.Path, "/api/auth/device/") && r.Header.Get("Authorization") != "Bearer private-session-token" { + t.Error("incorrect Inference.net session identity") + http.Error(w, "bad session", http.StatusUnauthorized) + return + } + if strings.HasPrefix(r.URL.Path, "/api/rest/") && r.Header.Get("x-inference-team-id") != "team" { + t.Error("incorrect Inference.net workspace identity") + } + var body map[string]any + if r.Method == http.MethodPost { + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + t.Errorf("invalid provider request body: %v", err) + http.Error(w, "invalid body", http.StatusBadRequest) + return + } + } + switch r.Method + " " + r.URL.Path { + case "GET /api/v1/key": + _, _ = w.Write([]byte(`{"data":{}}`)) + case "GET /api/v1/models": + _, _ = w.Write([]byte(`{"data":[{"id":"fixture-model","supports_tools":true,"output_modalities":["text"]},{"id":"compact-model"}]}`)) + case "POST /api/auth/device/code": + if body["client_id"] != inferencenet.DeviceClientID { + t.Error("incorrect device client identity") + } + _, _ = w.Write([]byte(`{"device_code":"private-device-code","user_code":"display-code","expires_in":60,"interval":1}`)) + case "POST /api/auth/device/token": + if body["client_id"] != inferencenet.DeviceClientID || body["device_code"] != "private-device-code" || body["grant_type"] != "urn:ietf:params:oauth:grant-type:device_code" { + t.Error("incorrect device token request") + } + _, _ = w.Write([]byte(`{"access_token":"private-session-token"}`)) + case "GET /api/auth/get-session": + _, _ = w.Write([]byte(`{"user":{"id":"person","email":"person@example.test"}}`)) + case "GET /api/auth/organization/list": + _, _ = w.Write([]byte(`[{"id":"team","name":"Team"},{"id":"other","name":"Other"}]`)) + case "POST /api/auth/organization/set-active": + if body["organizationId"] != "team" { + t.Error("incorrect active workspace") + } + _, _ = w.Write([]byte(`{}`)) + case "GET /api/rest/projects": + _, _ = w.Write([]byte(`[{"id":"existing","name":"Existing"},{"id":"other","name":"Other"}]`)) + case "POST /api/rest/projects/create": + if body["name"] != "Created" { + t.Error("project creation lost its trimmed name") + } + _, _ = w.Write([]byte(`{"id":"created","name":"Created"}`)) + case "POST /api/rest/api-keys": + project, _ := body["defaultProjectId"].(string) + name, _ := body["name"].(string) + if !slices.Contains([]string{"existing", "created"}, project) || body["teamId"] != "team" || !strings.HasPrefix(name, "whip-") { + t.Error("incorrect key provisioning identity") + } + wantScopes := []any{map[string]any{"permissions": []any{"read", "write"}, "projectId": project}} + if !reflect.DeepEqual(body["scopes"], wantScopes) { + t.Error("incorrect key provisioning scope") + } + _ = json.NewEncoder(w).Encode(map[string]string{"id": "key-" + project, "key": "private-machine-" + project}) + case "DELETE /api/rest/api-keys/key-created": + if r.URL.Query().Get("teamId") != "team" { + t.Error("logout archived a key under the wrong workspace") + } + _, _ = w.Write([]byte(`{}`)) + case "POST /api/auth/sign-out": + _, _ = w.Write([]byte(`{}`)) + default: + t.Errorf("unexpected provider fixture route: %s %s", r.Method, r.URL.Path) + http.Error(w, "unexpected request", http.StatusNotFound) + } + }) + t.Cleanup(inferencenet.SetURLsForTest(endpoint.URL, endpoint.URL, endpoint.URL+"/v1")) +} + +func waitProviderClientState(t *testing.T, client providerBehaviorClient, id, state string) ProviderLoginStatus { + t.Helper() + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + ticker := time.NewTicker(time.Millisecond) + defer ticker.Stop() + var result ProviderLoginStatus + for { + var err error + result, err = client.LoginStatus(ctx, id) + if err != nil { + t.Fatal(err) + } + if result.State == state { + return result + } + select { + case <-ctx.Done(): + t.Fatalf("wanted %s, got %s", state, result.State) + case <-ticker.C: + } + } +} diff --git a/internal/daemon/provider_openai_test.go b/internal/daemon/provider_openai_test.go index ee19696f9..8a2e9c075 100644 --- a/internal/daemon/provider_openai_test.go +++ b/internal/daemon/provider_openai_test.go @@ -2,8 +2,10 @@ package daemon import ( "context" + "encoding/base64" "encoding/json" "errors" + "net/http" "os" "path/filepath" "strings" @@ -265,26 +267,53 @@ func TestOpenAIRejectsConflictingProfileBeforeLogin(t *testing.T) { func TestOpenAILoginAcrossUnixAndWebSocketWithoutJournalingSecrets(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) - fixture := newV2Fixture(t, &fakeRunner{}) - service := fixture.server.providers - service.refreshModels = func(context.Context, string, config.Provider) error { return nil } ready, release := make(chan struct{}), make(chan struct{}) - service.openAILogin = func(ctx context.Context, onCode func(string, string)) (openaiauth.Credentials, error) { - onCode("https://auth.openai.com/codex/device", "private-device-code") - close(ready) - select { - case <-ctx.Done(): - return openaiauth.Credentials{}, ctx.Err() - case <-release: - return openAITestCredentials(), nil + providerHTTPFixture(t, []string{"auth.openai.com", "chatgpt.com"}, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.Method + " " + r.URL.Path { + case "POST /api/accounts/deviceauth/usercode": + _, _ = w.Write([]byte(`{"device_auth_id":"private-device-id","user_code":"private-device-code","interval":1}`)) + case "POST /api/accounts/deviceauth/token": + var body map[string]string + if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body["device_auth_id"] != "private-device-id" || body["user_code"] != "private-device-code" { + t.Error("device polling lost its authorization identity") + } + close(ready) + select { + case <-r.Context().Done(): + return + case <-release: + } + _, _ = w.Write([]byte(`{"authorization_code":"private-authorization-code","code_verifier":"private-code-verifier"}`)) + case "POST /oauth/token": + if err := r.ParseForm(); err != nil || r.Form.Get("code") != "private-authorization-code" || r.Form.Get("code_verifier") != "private-code-verifier" || r.Form.Get("grant_type") != "authorization_code" { + t.Error("token exchange lost its authorization identity") + } + idToken := "fixture." + base64.RawURLEncoding.EncodeToString([]byte(`{"chatgpt_account_id":"account-id","email":"account@example.com"}`)) + ".fixture" + _ = json.NewEncoder(w).Encode(map[string]any{ + "access_token": "private-access-token", "refresh_token": "private-refresh-token", "id_token": idToken, "expires_in": 3600, + }) + case "GET /backend-api/codex/models": + if r.Header.Get("Authorization") != "Bearer private-access-token" || r.Header.Get("Chatgpt-Account-Id") != "account-id" { + t.Error("subscription discovery lost its account identity") + } + _, _ = w.Write([]byte(`{"models":[{"slug":"gpt-5.5","visibility":"list","context_window":400000}]}`)) + default: + t.Errorf("unexpected OpenAI fixture route: %s %s", r.Method, r.URL.Path) + http.Error(w, "unexpected request", http.StatusNotFound) } - } + }) + fixture := newV2Fixture(t, &fakeRunner{}) local := fixture.dial("unix", "local-login") flow, err := local.BeginProviderLogin(t.Context(), openaiauth.Provider) if err != nil { t.Fatal(err) } - <-ready + select { + case <-ready: + case <-time.After(5 * time.Second): + t.Fatal("device authorization did not reach polling") + } _ = local.Close() remote := fixture.dial("websocket", "remote-login") recovered, err := remote.BeginProviderLogin(t.Context(), openaiauth.Provider) @@ -292,7 +321,7 @@ func TestOpenAILoginAcrossUnixAndWebSocketWithoutJournalingSecrets(t *testing.T) t.Fatalf("cross-transport login recovery: %v", err) } close(release) - waitProviderState(t, service, flow.FlowID, "succeeded") + waitProviderClientState(t, remote, flow.FlowID, "succeeded") status, err := remote.ProviderStatus(t.Context(), openaiauth.Provider) if err != nil || status.AuthState != "connected" { t.Fatalf("remote account status: %+v %v", status, err) diff --git a/internal/daemon/subscription_runtime_test.go b/internal/daemon/subscription_runtime_test.go index 9c7766891..d78514472 100644 --- a/internal/daemon/subscription_runtime_test.go +++ b/internal/daemon/subscription_runtime_test.go @@ -28,11 +28,18 @@ func (f subscriptionRuntimeTransport) RoundTrip(request *http.Request) (*http.Re func TestSubscriptionRecursiveRuntimeToolsHelpersTitleAndCompaction(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) - providers := NewProviderService(t.Context(), "subscription-runtime") - t.Cleanup(providers.Close) - if err := providers.openAI.Install(t.Context(), providers.openAI.Generation(), openAITestCredentials()); err != nil { + directory, err := config.Dir() + if err != nil { t.Fatal(err) } + credentials := openaiauth.New(t.Context(), directory) + if err := credentials.Install(t.Context(), credentials.Generation(), openAITestCredentials()); err != nil { + credentials.Close() + t.Fatal(err) + } + credentials.Close() + providers := NewProviderService(t.Context(), "subscription-runtime") + t.Cleanup(providers.Close) if _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { return cfg.UpsertOpenAICodex() }); err != nil { t.Fatal(err) } From cb959b12336d403ece55abd923afd09a4f98cc94 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:19:20 -0700 Subject: [PATCH 32/67] test(daemon): canonicalize provider fixture header --- internal/daemon/provider_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/daemon/provider_integration_test.go b/internal/daemon/provider_integration_test.go index 7597cd364..b10f67d52 100644 --- a/internal/daemon/provider_integration_test.go +++ b/internal/daemon/provider_integration_test.go @@ -77,7 +77,7 @@ func providerOnboardingHTTPFixture(t *testing.T) { http.Error(w, "bad session", http.StatusUnauthorized) return } - if strings.HasPrefix(r.URL.Path, "/api/rest/") && r.Header.Get("x-inference-team-id") != "team" { + if strings.HasPrefix(r.URL.Path, "/api/rest/") && r.Header.Get("X-Inference-Team-Id") != "team" { t.Error("incorrect Inference.net workspace identity") } var body map[string]any From dbde16ee7008038cf988ecf67b3e23aa1639a9c0 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:42:56 -0700 Subject: [PATCH 33/67] refactor(provider): separate host provider service from daemon --- Taskfile.yaml | 2 +- cmd/whip/daemon.go | 9 +- cmd/whip/subscription_test.go | 4 +- docs/architecture.md | 1 + docs/backend-reorganization-plan.md | 47 +- docs/features.md | 29 +- internal/daemon/architecture_test.go | 36 +- internal/daemon/client_control.go | 5 +- internal/daemon/daemon.go | 5 +- internal/daemon/main_test.go | 3 +- internal/daemon/mcp_import_service_test.go | 7 +- internal/daemon/provider_client.go | 19 + .../daemon/provider_client_behavior_test.go | 191 ------- .../daemon/provider_configuration_test.go | 471 +---------------- internal/daemon/provider_connections_test.go | 372 +------------ internal/daemon/provider_discovery_test.go | 144 ----- internal/daemon/provider_list_test.go | 82 +-- internal/daemon/provider_model_test.go | 473 ----------------- internal/daemon/provider_openai_test.go | 287 ---------- internal/daemon/provider_selection_test.go | 242 +-------- internal/daemon/provider_service_test.go | 402 +------------- internal/daemon/query.go | 3 +- internal/daemon/server.go | 5 +- internal/daemon/session.go | 3 +- internal/daemon/subscription_runtime_test.go | 3 +- .../default_permission_configuration_test.go | 9 +- internal/provider/main_test.go | 106 ++++ .../{daemon => provider}/provider_account.go | 48 +- internal/provider/provider_behavior_test.go | 207 ++++++++ .../{daemon => provider}/provider_catalog.go | 2 +- .../provider_configuration.go | 2 +- .../provider/provider_configuration_test.go | 495 ++++++++++++++++++ .../provider/provider_connections_test.go | 391 ++++++++++++++ .../provider_disconnect.go | 20 +- .../provider_discovery.go | 2 +- internal/provider/provider_discovery_test.go | 151 ++++++ .../{daemon => provider}/provider_error.go | 2 +- .../provider_error_test.go | 2 +- .../{daemon => provider}/provider_list.go | 20 +- internal/provider/provider_list_test.go | 103 ++++ .../{daemon => provider}/provider_model.go | 2 +- internal/provider/provider_model_test.go | 477 +++++++++++++++++ .../{daemon => provider}/provider_openai.go | 27 +- internal/provider/provider_openai_test.go | 304 +++++++++++ .../provider_selection.go | 4 +- internal/provider/provider_selection_test.go | 247 +++++++++ .../{daemon => provider}/provider_service.go | 121 ++--- internal/provider/provider_service_test.go | 441 ++++++++++++++++ 48 files changed, 3199 insertions(+), 2829 deletions(-) rename internal/{daemon => provider}/default_permission_configuration_test.go (83%) create mode 100644 internal/provider/main_test.go rename internal/{daemon => provider}/provider_account.go (59%) create mode 100644 internal/provider/provider_behavior_test.go rename internal/{daemon => provider}/provider_catalog.go (99%) rename internal/{daemon => provider}/provider_configuration.go (99%) create mode 100644 internal/provider/provider_configuration_test.go create mode 100644 internal/provider/provider_connections_test.go rename internal/{daemon => provider}/provider_disconnect.go (79%) rename internal/{daemon => provider}/provider_discovery.go (98%) create mode 100644 internal/provider/provider_discovery_test.go rename internal/{daemon => provider}/provider_error.go (98%) rename internal/{daemon => provider}/provider_error_test.go (98%) rename internal/{daemon => provider}/provider_list.go (93%) create mode 100644 internal/provider/provider_list_test.go rename internal/{daemon => provider}/provider_model.go (99%) create mode 100644 internal/provider/provider_model_test.go rename internal/{daemon => provider}/provider_openai.go (86%) create mode 100644 internal/provider/provider_openai_test.go rename internal/{daemon => provider}/provider_selection.go (97%) create mode 100644 internal/provider/provider_selection_test.go rename internal/{daemon => provider}/provider_service.go (82%) create mode 100644 internal/provider/provider_service_test.go diff --git a/Taskfile.yaml b/Taskfile.yaml index e7053fb67..a55895615 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -115,7 +115,7 @@ tasks: - npm run test:package - go test -race ./internal/rlm ./internal/session ./internal/daemon -run '^(TestScratch|TestWorkerSnapshot|TestWorkerRestore|TestWorkerCrossChunk|TestStructuredState|TestStatePages|TestChildScratchSurvivesDaemonRestart|TestPhaseFourAndFiveStoresAreRejectedWithoutMutation)' - - go test -race ./internal/llm ./internal/session ./internal/agent ./internal/daemon ./internal/tui -run '^(TestModel|TestPricing|TestUsage|TestStreamPreserves|TestStreamUnterminated|TestCompletePreserves|TestMalformedUsage)' + - go test -race ./internal/llm ./internal/session ./internal/agent ./internal/daemon ./internal/provider ./internal/tui -run '^(TestModel|TestPricing|TestUsage|TestStreamPreserves|TestStreamUnterminated|TestCompletePreserves|TestMalformedUsage)' contract: desc: "Validate local protocol artifacts and deterministic generation (run task generate first)" diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index 9e4e13045..a6c8aed7f 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -16,6 +16,7 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/agentdef" @@ -94,7 +95,7 @@ func runDaemon(ctx context.Context, args []string) error { return err } limits := rlmLimits(cfg.RLM) - providers := daemon.NewProviderService(ctx, strconv.FormatInt(generation, 10)) + providers := providersvc.NewProviderService(ctx, strconv.FormatInt(generation, 10)) defer providers.Close() if discovered, discoveryErr := providers.DiscoverProviders(ctx, "", ""); discoveryErr != nil { config.LogEvent("provider.discovery", discoveryErr.Error()) @@ -265,7 +266,7 @@ func configureRuntimeCompaction( ag *agent.Agent, cfg *config.Config, defaults agentdef.CompactionDefaults, - providers *daemon.ProviderService, + providers *providersvc.ProviderService, ) { ag.CompactThreshold = defaults.Threshold if ag.CompactThreshold == 0 { @@ -300,7 +301,7 @@ func configureRuntimeCompaction( // resolveRuntimeModel snapshots the actual endpoint and its catalog rates together. // All model purposes use this resolver so a default provider cannot accidentally // supply another endpoint's price or output limits. -func resolveRuntimeModel(cfg *config.Config, modelName, providerName string, services ...*daemon.ProviderService) (agent.ModelRoute, config.Model, error) { +func resolveRuntimeModel(cfg *config.Config, modelName, providerName string, services ...*providersvc.ProviderService) (agent.ModelRoute, config.Model, error) { providerName, provider, model, apiID, err := cfg.ResolveRoute(modelName, providerName) if err != nil { return agent.ModelRoute{}, config.Model{}, err @@ -308,7 +309,7 @@ func resolveRuntimeModel(cfg *config.Config, modelName, providerName string, ser if modelName == "" { modelName = cfg.DefaultModel } - var providers *daemon.ProviderService + var providers *providersvc.ProviderService if len(services) > 0 { providers = services[0] } diff --git a/cmd/whip/subscription_test.go b/cmd/whip/subscription_test.go index 10faf6ac7..4a2b30170 100644 --- a/cmd/whip/subscription_test.go +++ b/cmd/whip/subscription_test.go @@ -7,9 +7,9 @@ import ( "time" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/openaiauth" + providersvc "github.com/context-labs/whip/internal/provider" ) func TestResolveSubscriptionRouteUsesHostCredentialsAndLimits(t *testing.T) { @@ -23,7 +23,7 @@ func TestResolveSubscriptionRouteUsesHostCredentialsAndLimits(t *testing.T) { t.Fatal(err) } auth.Close() - providers := daemon.NewProviderService(t.Context(), "subscription-route") + providers := providersvc.NewProviderService(t.Context(), "subscription-route") t.Cleanup(providers.Close) cfg := config.Default() if err := cfg.UpsertOpenAICodex(); err != nil { diff --git a/docs/architecture.md b/docs/architecture.md index d2a673be8..2d39c09a7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -141,6 +141,7 @@ budgets, and private transcript. | --- | --- | | `internal/protocol`, `packages/protocol` | typed operation/event contract, generated Draft-07 schemas, TypeScript and Ajv | | `internal/daemon` | shared handlers, Unix/WebSocket/HTTP adapters, root actors, recursive runtime, lifecycle | +| `internal/provider` | host provider configuration, discovery, catalogs and account login lifetimes; borrows existing config/auth storage and exposes operations to daemon without importing it | | `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery | | `internal/agentdef` | agent definitions and their registry: instructions and discovery toggles, selected modules and capabilities, model and compaction defaults, named children, and the capability-to-operation mapping; `Coding()` and `JuniorDeveloper()` are the first-party definitions | | `internal/rlm` | kernel process, Starlark modules, runtime guide fragments, focused-context composer | diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index eeb64a539..e3363f59c 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -661,7 +661,8 @@ checks on an earlier head are not a claim that a current-head rerun has finished | Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681287194) passed, including SDK/UI/browser/product, both compatibility jobs, Go tests with the 90% coverage floor, lint, runtime, mobile, builds, docs, desktop and distribution. Current security also passed; this is the combined green prerequisite baseline. | | Host MCP ownership (plan PR 2) | `d8175212d3db3371b14862dc07ad24fc62393108`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite (250.722s) passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. [Full current CI](https://github.com/context-labs/whip/actions/runs/36682214774) and current security passed. | | Provider operation boundary (plan PR 3a) | `a211fb0e7629f9692eb5133aa00244aea17e38a9`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog operation/reload characterization passed three times under the race detector on unchanged production code before extraction. Typed catalog results, compaction validation, model admission and provider-context borrowing now form the narrow operation surface. Shared effort and permission-default helpers move once to their existing configuration/session owners. Validation results are recorded below. [Current CI](https://github.com/context-labs/whip/actions/runs/36683418233) is running; current security passed. | -| Provider integration test boundary (plan PR 3b1) | This change, based on `a211fb0e7629f9692eb5133aa00244aea17e38a9`. | The five existing affected integration tests now use HTTP/auth persistence rather than private provider callbacks. They passed three times under the race detector (23.256s). Full-module build, vet and whipvet and fresh fixed-SDK compatibility passed. The full daemon race/shuffle suite passed (261.125s). | +| Provider integration test boundary (plan PR 3b1) | `d81f814b139d3a2320db6942e02c22a3e54d9b80`, [PR #306](https://github.com/context-labs/whip/pull/306). | The five existing affected integration tests now use HTTP/auth persistence rather than private provider callbacks. They passed three times under the race detector (23.256s). Full-module build, vet and whipvet and fresh fixed-SDK compatibility passed. The full daemon race/shuffle suite passed (261.125s). [Current CI](https://github.com/context-labs/whip/actions/runs/36684285340) is running; current security passed. | +| Provider package extraction (plan PR 3b2) | This change, based on `d81f814b139d3a2320db6942e02c22a3e54d9b80`. | Eleven implementation files move to `internal/provider` with their existing service and constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing test functions remain. Provider-private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. Validation results are recorded below. | ### Host MCP ownership and lifetime @@ -737,3 +738,47 @@ built all three selected integration binaries freshly. SDK and generated contract artifacts matched; both transport comparisons, deliberate mutation rejection, lifecycle checks, and both-engine fixed/base → candidate → base data rollback passed. Production source, SDK, schema and CI requirements are unchanged. + +### Provider package ownership + +`internal/provider` owns the existing `ProviderService` implementation and its +private configuration, discovery, catalog and account helpers. The service still +uses the same configuration, authentication, model-client and permission-default +dependencies. Daemon constructs or receives it at the same call sites and closes +it at the same lifetime boundaries. Host MCP borrows the exact provider context +through `Context`; no resource or shutdown order changes. + +Daemon retains RPC decoding, native client methods, protocol type aliases, query +deadlines and serialization. The provider package uses existing protocol values +directly and has no daemon import or forwarding service implementation. A narrow +architecture test enforces that import direction. Model-call checks cover both +packages and exempt only `internal/daemon/agent_session.go`. + +Private service tests move with their implementation. Both packages retain +equivalent temporary-home and provider-environment isolation, including a +child-process regression. All existing test bodies are preserved after type +qualification except the expanded architecture scan and the approved Cerebras +catalog read helper, which now reads the typed service result with unchanged +membership, request-count, error, restart and cache assertions. Daemon client +tests and the frozen guard retain serialization coverage. The named model +acceptance command adds the provider package so the moved snapshot test remains +selected; its original packages, regex and all CI requirements are unchanged. + +Local build, vet, whipvet and integration-fixture compilation passed. The full +provider and daemon race/shuffle suites passed (3.078s and 252.881s), as did the +relevant CLI startup/routing/compaction/authentication tests (5.804s). Focused +architecture checks passed after adding the import guard (1.717s); JSON test +events confirm the moved model-snapshot acceptance test ran and passed. The +declaration comparison accounts for 80 declarations in the new package and +preserves every existing production declaration. The test-name comparison +preserves all 758 existing tests and adds only provider-environment isolation +and the provider-to-daemon import guard. + +Fresh compatibility evidence at `/private/tmp/whip-reorg-03b2-compat-evidence/evidence.json` +passed against the fixed SDK revision `271c0f8d2a35648d1b45056d57432590b783483c` +and immediate base `d81f814b139d3a2320db6942e02c22a3e54d9b80`. Freshly built +fixed/base/candidate binaries passed both transport comparisons, actual response +and ordering mutation rejection, lifecycle checks, and both-engine retained +root/child/content/schema/trace rollback. All new files were staged before the +run captured its candidate diff. Later ledger additions record these results; +production and test source match the captured candidate. diff --git a/docs/features.md b/docs/features.md index fca524391..cad64fe02 100644 --- a/docs/features.md +++ b/docs/features.md @@ -354,7 +354,7 @@ rotation. OpenCode credential/config/database import and desktop probes are remo Code: `cmd/modelgen`, `internal/config/modelsdev`, `internal/config/{modelsdev,provider_credentials,provider_models,revision}.go`, -`internal/daemon/provider_{discovery,list,configuration,model,service}.go`, +`internal/provider/provider_{discovery,list,configuration,model,service}.go`, `internal/tui/setup.go`, `packages/app/src/provider-setup.tsx`, `apps/desktop/src/provider-environment.ts`. Tests: importer/presence/pricing tests in `cmd/modelgen` and @@ -382,11 +382,12 @@ appear in their own Settings group. Disconnect also clears the disabled flag. Mo rejects stale route/account responses. Desktop recovers only the supported local shell keys, bounded and without forwarding them to remote hosts. -Code: `internal/config/providers.go`, `internal/daemon/provider_{list,disconnect,model}.go`, +Code: `internal/config/providers.go`, `internal/provider/provider_{list,disconnect,model}.go`, `internal/daemon/budget.go`, `packages/app/src/settings/provider-connections.tsx`, `packages/app/src/settings/provider-login.tsx`, and `apps/desktop/src/runtime.ts`. Tests: `internal/config/providers_test.go`, -`internal/daemon/provider_connections_test.go`, `packages/sdk/test/services.test.ts`, +`internal/provider/provider_connections_test.go`, `internal/daemon/provider_connections_test.go`, +`packages/sdk/test/services.test.ts`, `packages/app/test/provider-connections.test.tsx`, `packages/app/test/model-selection.test.tsx`, `apps/desktop/tests/provider-environment.test.ts`, and the production `apps/web/scripts/provider-connections.mjs` workflow. See the @@ -440,12 +441,13 @@ cleared by an earlier acceptance. Native **Set up this Mac** composes verified backend installation and the existing connection owner in one action. Existing installations, advanced diagnostics and remote hosts retain their policies. -Code: `internal/daemon/provider_selection.go`, `internal/daemon/provider_service.go`, +Code: `internal/provider/provider_selection.go`, `internal/provider/provider_service.go`, `internal/tui/{setup,startup}.go`, `internal/daemon/root_client.go`, `internal/session/command.go`, `packages/app/src/{provider-setup,welcome,welcome-submission,runtime}.ts*`, `packages/app/src/host-dialog.tsx`, and `apps/desktop/src/runtime.ts`. -Tests: `internal/daemon/{provider_selection,root_client}_test.go`, +Tests: `internal/provider/provider_selection_test.go`, +`internal/daemon/{provider_selection,root_client}_test.go`, `internal/tui/{setup,startup,client,cursor}_test.go`, `internal/session/command_test.go`, `cmd/whip/daemon_test.go`, `packages/app/test/{provider-connections,welcome-submission,sidebar-creation,runtime,local-runtime}.test.ts*`, @@ -497,10 +499,10 @@ acceptance is implied. Code: `internal/tui/setup_picker.go`, `internal/tui/ui/list.go`, `internal/config/{providers,provider_credentials,provider_models}.go`, -`internal/daemon/provider_{list,model,service}.go`, +`internal/provider/provider_{list,model,service}.go`, `internal/llm/provider_compatibility.go`, `apps/desktop/src/runtime.ts`. Tests: `internal/tui/setup_picker_test.go`, credential/preset model tests under -`internal/config`, preset discovery/key tests under `internal/daemon`, +`internal/config`, preset discovery/key tests under `internal/provider`, `internal/llm/provider_compatibility_test.go`, and desktop provider environment tests. See [picker implementation and evidence](../.ai-docs/plans/tui-provider-configuration/PICKER-REDESIGN.md). One-step defaults: `internal/tui/setup_default{,_test}.go`, @@ -526,11 +528,11 @@ history. Web/desktop inventory sees the same connections. No provider database o web custom-provider form is introduced. Code: `internal/tui/setup_provider.go`, `internal/tui/setup_host.go`, -`internal/daemon/provider_configuration.go`, `internal/config/providers.go`, +`internal/provider/provider_configuration.go`, `internal/config/providers.go`, `internal/llm/openai.go`, `internal/protocol/provider_types.go`, and `packages/sdk/src/services.ts`. Tests: `internal/tui/setup_provider_test.go`, -`internal/daemon/provider_configuration_test.go`, +`internal/provider/provider_configuration_test.go`, `internal/daemon/provider_configuration_test.go`, `internal/config/provider_auth_test.go`, `internal/llm/openai_noauth_test.go`, `cmd/whip/acp_test.go`, and `packages/sdk/test/services.test.ts`. See [configuration instructions](models-providers.md#supported-provider-types-and-custom-endpoints) @@ -551,11 +553,12 @@ setup and limits; live acceptance is tracked in the [implementation plan](../.ai-docs/plans/openai-subscriptions/README.md). Code: `internal/openaiauth`, `internal/llm/{subscription,responses}.go`, -`internal/daemon/provider_{openai,model}.go`, `cmd/whip/auth_openai.go`, +`internal/provider/provider_{openai,model}.go`, `cmd/whip/auth_openai.go`, `internal/tui/auth_cmd.go`, `packages/app/src/settings/providers.tsx`, and `packages/app/src/model-options.ts`. Tests: `internal/openaiauth/auth_test.go`, `internal/llm/{subscription,responses}_test.go`, -`internal/daemon/provider_openai_test.go`, `internal/session/continuation_test.go`, +`internal/provider/provider_openai_test.go`, `internal/daemon/provider_openai_test.go`, +`internal/session/continuation_test.go`, and `packages/app/test/{providers,model-selection}.test.tsx` cover rotation races, cross-transport login recovery, secret isolation, stream completion, budgeting, model/provider selection and client state. Live Pro-account acceptance also @@ -616,7 +619,7 @@ verified tools, helpers, a child, images, title/compaction and restart recovery. the daemon host. TUI themes/keybindings remain local. Secret credentials and ephemeral terminal input are excluded from command journals. - Implementation: `internal/protocol`, `internal/daemon/{server,subscription, - transport,provider_service,completion}.go`, `internal/webgateway`, `internal/session`, and + transport,completion}.go`, `internal/provider/provider_service.go`, `internal/webgateway`, `internal/session`, and `packages/protocol`. Coverage: `v2_acceptance_test.go`, `runtime_parity_test.go`, `transport_test.go`, `client_admission_test.go`, provider/config tests and the generated contract/browser interoperability checks. See [protocol-v2.md](protocol-v2.md). @@ -1326,7 +1329,7 @@ Other custom origins, wildcards, suffixes, ports and paths remain rejected. validation, explicit opt-in and CORS response headers; the daemon no longer hosts HTTP handlers. -Code: `internal/config/remote_hosts.go`, `internal/daemon/provider_service.go`, +Code: `internal/config/remote_hosts.go`, `internal/provider/provider_service.go`, `packages/app/src/{hosts,runtime,session-tabs,workspace-views}.ts`, `{host-dialog,welcome,settings,session-search-dialog,attention}.tsx`. Tests: `internal/config/remote_hosts_test.go`, the remote-host configuration test diff --git a/internal/daemon/architecture_test.go b/internal/daemon/architecture_test.go index 22a839ef1..79c71db2a 100644 --- a/internal/daemon/architecture_test.go +++ b/internal/daemon/architecture_test.go @@ -1,10 +1,13 @@ package daemon import ( + "go/parser" + "go/token" "io/fs" "os" "path/filepath" "runtime" + "strconv" "strings" "testing" ) @@ -43,13 +46,34 @@ func productionGoFiles(t *testing.T, directory string) map[string]string { func TestArchitectureKeepsProviderCallsBehindAgentSession(t *testing.T) { root := repositoryRoot(t) - for path, body := range productionGoFiles(t, filepath.Join(root, "internal", "daemon")) { - if filepath.Base(path) == "agent_session.go" { - continue + for _, name := range []string{"daemon", "provider"} { + for path, body := range productionGoFiles(t, filepath.Join(root, "internal", name)) { + if path == filepath.Join(root, "internal", "daemon", "agent_session.go") { + continue + } + for _, call := range []string{".Complete(", ".Stream("} { + if strings.Contains(body, call) { + t.Errorf("model provider call %q escaped AgentSession: %s", call, path) + } + } } - for _, call := range []string{".Complete(", ".Stream("} { - if strings.Contains(body, call) { - t.Errorf("model provider call %q escaped AgentSession: %s", call, path) + } +} + +func TestArchitectureKeepsProviderIndependentOfDaemon(t *testing.T) { + root := repositoryRoot(t) + for path, body := range productionGoFiles(t, filepath.Join(root, "internal", "provider")) { + file, err := parser.ParseFile(token.NewFileSet(), path, body, parser.ImportsOnly) + if err != nil { + t.Fatal(err) + } + for _, imported := range file.Imports { + name, err := strconv.Unquote(imported.Path.Value) + if err != nil { + t.Fatal(err) + } + if name == "github.com/context-labs/whip/internal/daemon" { + t.Errorf("provider imports daemon: %s", path) } } } diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index 47af76224..f27b168e3 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -21,6 +21,7 @@ import ( "github.com/context-labs/whip/internal/lsp" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/schedule" sessionstore "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" @@ -1786,11 +1787,11 @@ func marshalClientOutput(value any, err error) (string, error) { return string(raw), err } -func clientProviderCatalogs(ctx context.Context, providers *ProviderService, refresh bool) (string, error) { +func clientProviderCatalogs(ctx context.Context, providers *providersvc.ProviderService, refresh bool) (string, error) { return clientProviderCatalogsFor(ctx, providers, refresh, "") } -func clientProviderCatalogsFor(ctx context.Context, providers *ProviderService, refresh bool, selected string) (string, error) { +func clientProviderCatalogsFor(ctx context.Context, providers *providersvc.ProviderService, refresh bool, selected string) (string, error) { result, err := providers.ListCatalogs(ctx, refresh, selected) return marshalClientOutput(result, err) } diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 1ea3866ae..fa0f4369a 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -9,6 +9,7 @@ import ( "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/terminal" ) @@ -25,7 +26,7 @@ type rootEntry struct { // Daemon owns the durable store and exactly one live actor per opened root. type Daemon struct { - providers *ProviderService + providers *providersvc.ProviderService store *session.Store factory Factory control *Control @@ -47,7 +48,7 @@ type Daemon struct { } // New applies daemon-startup recovery before any root can be opened. -func New(store *session.Store, factory Factory, providers ...*ProviderService) (*Daemon, error) { +func New(store *session.Store, factory Factory, providers ...*providersvc.ProviderService) (*Daemon, error) { if store == nil || factory == nil { return nil, errors.New("daemon requires a store and root factory") } diff --git a/internal/daemon/main_test.go b/internal/daemon/main_test.go index e24e44c9b..7d616ae29 100644 --- a/internal/daemon/main_test.go +++ b/internal/daemon/main_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/context-labs/whip/internal/config" + providersvc "github.com/context-labs/whip/internal/provider" ) // Model requests and discovery in tests must not depend on, or expose, the @@ -89,7 +90,7 @@ func TestDaemonTestEnvironment(t *testing.T) { if got := cfg.EffectiveProviders(); len(got) != 0 { t.Errorf("empty fixture discovered %d inherited providers", len(got)) } - service := NewProviderService(t.Context(), "isolated-test-environment") + service := providersvc.NewProviderService(t.Context(), "isolated-test-environment") t.Cleanup(service.Close) if _, err := queryProviderCatalogs(t.Context(), service, json.RawMessage(`{}`)); err != nil { t.Fatal(err) diff --git a/internal/daemon/mcp_import_service_test.go b/internal/daemon/mcp_import_service_test.go index a9fe7ed4a..2f264b84a 100644 --- a/internal/daemon/mcp_import_service_test.go +++ b/internal/daemon/mcp_import_service_test.go @@ -20,6 +20,7 @@ import ( "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" ) @@ -28,7 +29,7 @@ import ( // empty OpenCode slot, and returns both host services plus a project directory. The // state rules themselves are pinned in internal/mcp; these tests cover what // the service adds on top. -func mcpImportFixture(t *testing.T) (*hostMCPService, *ProviderService, string) { +func mcpImportFixture(t *testing.T) (*hostMCPService, *providersvc.ProviderService, string) { t.Helper() home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) @@ -55,9 +56,9 @@ func mcpImportFixture(t *testing.T) (*hostMCPService, *ProviderService, string) mcp.ClaudeGlobalPath = func() string { return filepath.Join(project, "absent-claude.json") } mcp.OpenCodePaths = func() []string { return []string{filepath.Join(project, "opencode.jsonc")} } t.Cleanup(func() { mcp.CodexPath, mcp.ClaudeGlobalPath, mcp.OpenCodePaths = origC, origG, origOC }) - service := NewProviderService(t.Context(), "mcp-import") + service := providersvc.NewProviderService(t.Context(), "mcp-import") t.Cleanup(service.Close) - return &hostMCPService{ctx: service.ctx}, service, project + return &hostMCPService{ctx: service.Context()}, service, project } func TestMCPImportCandidatesReportOfferPathAndUnreadableSources(t *testing.T) { diff --git a/internal/daemon/provider_client.go b/internal/daemon/provider_client.go index 4eb376498..b5e069038 100644 --- a/internal/daemon/provider_client.go +++ b/internal/daemon/provider_client.go @@ -8,6 +8,25 @@ import ( "github.com/context-labs/whip/internal/protocol" ) +// RuntimeConfiguration contains settings safe to send to clients. Credentials +// and integration definitions stay on the execution host. +type RuntimeConfiguration = protocol.RuntimeConfiguration + +type ConfigurationUpdate = protocol.ConfigurationUpdate + +// ProviderKeySetup is ephemeral: never write it to a command journal or log. +type ProviderKeySetup = protocol.ProviderKeySetup + +type ProviderChoice = protocol.ProviderChoice + +type ProviderLoginStatus = protocol.ProviderLoginStatus + +type ( + ProviderLoginList = protocol.ProviderLoginList + ProviderNameParams = protocol.ProviderNameParams + ProviderStatus = protocol.ProviderStatus +) + // providerCall waits for a connection but never retries an issued mutation. // Callers can query login status after reconnect; credentials are never replayed. func (c *RootClient) providerCall(ctx context.Context, method string, params, result any) error { diff --git a/internal/daemon/provider_client_behavior_test.go b/internal/daemon/provider_client_behavior_test.go index f7fd291c1..a12cdfd53 100644 --- a/internal/daemon/provider_client_behavior_test.go +++ b/internal/daemon/provider_client_behavior_test.go @@ -227,67 +227,6 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes } } -func TestProviderConfigurationRejectsInvalidChangesAtomically(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "validation") - defer service.Close() - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - for _, tc := range []struct { - name string - change ConfigurationUpdate - }{ - {"missing revision", ConfigurationUpdate{}}, - {"effort", ConfigurationUpdate{Revision: before.Revision, DefaultEffort: new("turbo")}}, - {"negative compact", ConfigurationUpdate{Revision: before.Revision, CompactPercent: new(-1)}}, - {"large compact", ConfigurationUpdate{Revision: before.Revision, CompactPercent: new(101)}}, - {"rounds", ConfigurationUpdate{Revision: before.Revision, GoalMaxRounds: new(-1)}}, - {"retries", ConfigurationUpdate{Revision: before.Revision, MaxRetries: new(-1)}}, - } { - t.Run(tc.name, func(t *testing.T) { - if _, err := service.UpdateConfiguration(tc.change); err == nil { - t.Fatal("invalid update accepted") - } - after, err := service.ReadConfiguration() - if err != nil || !reflect.DeepEqual(after, before) { - t.Fatalf("failed update changed configuration: %+v %v", after, err) - } - }) - } - for _, p := range []ProviderKeySetup{{}, {Revision: before.Revision, Provider: "unknown"}, {Revision: before.Revision, Provider: "openrouter"}} { - if _, err := service.SetProviderKey(t.Context(), p); err == nil { - t.Fatal("invalid key setup accepted") - } - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, errors.New("provider leaked secret-key") - } - if _, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "key"}); err == nil || strings.Contains(err.Error(), "secret-key") { - t.Fatalf("unsafe validation failure: %v", err) - } - if _, err := service.LoginStatus(""); err == nil { - t.Fatal("empty login identity accepted") - } - if _, err := service.CancelLogin("missing"); err == nil { - t.Fatal("missing login cancelled") - } - if _, err := service.SelectLoginTeam("missing", "team"); err == nil { - t.Fatal("missing login selected team") - } - if _, err := service.SelectLoginProject("missing", "project"); err == nil { - t.Fatal("missing login selected project") - } - if _, err := service.CreateLoginProject("missing", ""); err == nil { - t.Fatal("blank project name accepted") - } - service.Close() - if _, err := service.BeginLogin(); !errors.Is(err, context.Canceled) { - t.Fatalf("closed login service: %v", err) - } -} - func TestRootProviderValidationUsesEphemeralConnection(t *testing.T) { _, _, root, _ := providerBehaviorFixture(t) endpoint := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -315,133 +254,3 @@ func TestRootProviderValidationUsesEphemeralConnection(t *testing.T) { t.Fatalf("closed config read=%v", err) } } - -func TestProviderLoginFailuresAndCancellationNeverReportSuccess(t *testing.T) { - for _, stage := range []string{"projects", "create", "finish", "cancel_provisioning", "cancel_projects"} { - t.Run(stage, func(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "failure") - defer service.Close() - entered := make(chan struct{}) - service.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { - return providerLoginIdentity{token: "private-token", teams: []inferencenet.Team{{ID: "team"}, {ID: "other"}}}, nil - } - service.projects = func(ctx context.Context, _ string, _ inferencenet.Team) ([]inferencenet.Project, error) { - if stage == "projects" { - return nil, errors.New("upstream leaked private-token") - } - if stage == "cancel_projects" { - close(entered) - <-ctx.Done() - return nil, ctx.Err() - } - return []inferencenet.Project{{ID: "project"}, {ID: "other"}}, nil - } - service.create = func(context.Context, string, inferencenet.Team, string) (inferencenet.Project, error) { - return inferencenet.Project{}, errors.New("upstream leaked private-token") - } - service.finish = func(ctx context.Context, _ inferencenet.Auth) error { - if stage == "cancel_provisioning" { - close(entered) - <-ctx.Done() - return ctx.Err() - } - return errors.New("upstream leaked private-token") - } - flow, err := service.BeginLogin() - if err != nil { - t.Fatal(err) - } - waitProviderState(t, service, flow.FlowID, "choose_team") - if _, err := service.SelectLoginTeam(flow.FlowID, "team"); err != nil { - t.Fatal(err) - } - if stage != "projects" && stage != "cancel_projects" { - waitProviderState(t, service, flow.FlowID, "choose_project") - if stage == "create" { - _, err = service.CreateLoginProject(flow.FlowID, "created") - } else { - _, err = service.SelectLoginProject(flow.FlowID, "project") - } - if err != nil { - t.Fatal(err) - } - } - want := "failed" - if strings.HasPrefix(stage, "cancel_") { - select { - case <-entered: - case <-time.After(2 * time.Second): - t.Fatal("provider operation did not begin") - } - if _, err := service.CancelLogin(flow.FlowID); err != nil { - t.Fatal(err) - } - want = "cancelled" - if stage == "cancel_provisioning" { - want = "interrupted" - } - } - status := waitProviderState(t, service, flow.FlowID, want) - service.Close() - final, err := service.LoginStatus(flow.FlowID) - if err != nil || final.State != want || final.ProjectID != "" { - t.Fatalf("late completion changed terminal status: %+v %v", final, err) - } - encoded, err := json.Marshal(status) - if err != nil || strings.Contains(string(encoded), "private-token") { - t.Fatalf("secret escaped terminal state: %s %v", encoded, err) - } - if _, err := service.SelectLoginProject(flow.FlowID, "project"); err == nil { - t.Fatal("terminal login allowed another provisioning attempt") - } - }) - } -} - -func TestProviderCompletionPersistsCredentialsOnlyBeforeCancellation(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "persist") - defer service.Close() - auth := inferencenet.Auth{UserEmail: "owner@example.test", TeamName: "Test workspace", ProjectID: "project", ProjectName: "Project", MachineKey: "machine-secret", MachineKeyName: "Host"} - ctx, cancel := context.WithCancel(t.Context()) - cancel() - if err := service.finish(ctx, auth); !errors.Is(err, context.Canceled) { - t.Fatalf("cancelled completion=%v", err) - } - before, err := inferencenet.LoadAuth() - if err != nil || before.MachineKey != "" { - t.Fatalf("cancelled completion persisted credentials: %+v %v", before, err) - } - if err := service.finish(t.Context(), inferencenet.Auth{}); err == nil { - t.Fatal("completion without project credentials accepted") - } - if err := service.finish(t.Context(), auth); err != nil { - t.Fatal(err) - } - loaded, err := inferencenet.LoadAuth() - if err != nil || loaded.MachineKey != auth.MachineKey || loaded.ProjectID != auth.ProjectID || loaded.TeamName != auth.TeamName { - t.Fatalf("completion did not persist host credentials: %v", err) - } - status, err := service.ProviderStatus(config.InferenceNetProvider) - if err != nil || !status.Configured || status.Email != auth.UserEmail || status.TeamName != auth.TeamName || status.KeySource != "machine" || status.MachineKeyName != "Host" { - t.Fatalf("safe account identity=%+v %v", status, err) - } - beforeConfig, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - validationCtx, stopValidation := context.WithCancel(t.Context()) - defer stopValidation() - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - stopValidation() - return []llm.ModelInfo{{ID: "valid"}}, nil - } - if _, err := service.SetProviderKey(validationCtx, ProviderKeySetup{Revision: beforeConfig.Revision, Provider: "openrouter", Key: "replacement-secret"}); !errors.Is(err, context.Canceled) { - t.Fatalf("cancelled key setup=%v", err) - } - afterConfig, err := service.ReadConfiguration() - if err != nil || !reflect.DeepEqual(afterConfig, beforeConfig) { - t.Fatalf("cancelled key setup changed config: %+v %v", afterConfig, err) - } -} diff --git a/internal/daemon/provider_configuration_test.go b/internal/daemon/provider_configuration_test.go index 3f969191e..2844d86d8 100644 --- a/internal/daemon/provider_configuration_test.go +++ b/internal/daemon/provider_configuration_test.go @@ -1,32 +1,24 @@ package daemon import ( - "context" "encoding/json" - "errors" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "reflect" "strings" "testing" - "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/openaiauth" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" ) -func customProviderService(t *testing.T) *ProviderService { +func customProviderService(t *testing.T) *providersvc.ProviderService { t.Helper() t.Setenv("WHIPCODE_HOME", t.TempDir()) - s := NewProviderService(t.Context(), "provider-configuration") + s := providersvc.NewProviderService(t.Context(), "provider-configuration") t.Cleanup(s.Close) return s } -func customProviderParams(t *testing.T, s *ProviderService) protocol.ProviderCreateParams { +func customProviderParams(t *testing.T, s *providersvc.ProviderService) protocol.ProviderCreateParams { t.Helper() cfg, err := s.ReadConfiguration() if err != nil { @@ -39,425 +31,6 @@ func customProviderParams(t *testing.T, s *ProviderService) protocol.ProviderCre } } -func TestProviderConfigurationCreatePersistAndNoAuthRequests(t *testing.T) { - s := customProviderService(t) - requests := 0 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - requests++ - if r.Header.Get("Authorization") != "" { - t.Error("unauthenticated discovery sent an Authorization header") - } - if r.URL.Path != "/v1/models" { - t.Errorf("unexpected request %s", r.URL.Path) - } - _, _ = w.Write([]byte(`{"data":[{"id":"fixture-model"}]}`)) - })) - defer server.Close() - p := customProviderParams(t, s) - p.Definition.BaseURL, p.Credential = server.URL+"/v1/", protocol.ProviderCredential{Mode: "none"} - before, _ := config.Load() - created, err := s.CreateProvider(t.Context(), p) - if err != nil { - t.Fatal(err) - } - if requests != 1 || created.Discovery.Status != "loaded" || created.Credential.Mode != "none" || created.Credential.Available == nil || !*created.Credential.Available { - t.Fatalf("incorrect discovery/readiness: %+v, requests %d", created, requests) - } - cfg, err := config.Load() - if err != nil { - t.Fatal(err) - } - if cfg.Providers[p.Provider].Auth != "none" || cfg.DefaultModel != before.DefaultModel || cfg.DefaultProvider != before.DefaultProvider || !reflect.DeepEqual(cfg.Models, before.Models) { - t.Fatal("provider save did not preserve authentication/defaults/models") - } - restarted := NewProviderService(t.Context(), "new-generation") - defer restarted.Close() - read, err := restarted.ReadProvider(p.Provider) - if err != nil || read.Revision != created.Revision || read.Credential.Mode != "none" { - t.Fatalf("restart: %+v %v", read, err) - } - client, err := restarted.ModelClient(cfg.Providers[p.Provider]) - if err != nil || client.APIKey != "" { - t.Fatalf("no-auth model client: %v", err) - } - if _, err := s.CreateProvider(t.Context(), p); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatalf("stale create: %v", err) - } - p.Revision = read.Revision - if _, err := s.CreateProvider(t.Context(), p); err == nil { - t.Fatal("duplicate provider ID accepted") - } -} - -func TestProviderConfigurationRedactedReadAndMetadataUpdate(t *testing.T) { - s := customProviderService(t) - marker := filepath.Join(t.TempDir(), "must-not-execute") - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["custom-test"] = config.Provider{Name: "Original", BaseURL: "https://example.test/v1", APIKey: "!touch " + marker} - return nil - }) - if err != nil { - t.Fatal(err) - } - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - t.Fatal("metadata-only save performed discovery") - return nil, nil - } - read, err := s.ReadProvider("custom-test") - if err != nil { - t.Fatal(err) - } - body, _ := json.Marshal(read) - if strings.Contains(string(body), marker) || strings.Contains(string(body), "touch") || read.Credential.Mode != "command" { - t.Fatalf("secret reference exposed: %s", body) - } - updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{ - Revision: read.Revision, Provider: read.Provider, Name: new("Renamed"), - ManualModel: &protocol.ProviderManualModel{Alias: "custom-test/private-model", ID: "private-model", Context: 4096, MaxOutput: 1024}, - }) - if err != nil { - t.Fatal(err) - } - if updated.Discovery.Status != "not_checked" || len(updated.Models) != 1 || updated.Models[0].ID != "private-model" { - t.Fatalf("incorrect alias save: %+v", updated) - } - if _, err := os.Stat(marker); !os.IsNotExist(err) { - t.Fatal("read or metadata-only update executed the secret command") - } - cfg, _ := config.Load() - if cfg.Providers[read.Provider].APIKey != "!touch "+marker { - t.Fatal("name edit replaced the existing credential") - } - for _, credential := range []*protocol.ProviderCredential{nil, {Mode: "keep"}} { - _, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Revision: updated.Revision, Provider: read.Provider, BaseURL: new("https://other.test/v1"), Credential: credential}) - if err == nil || !strings.Contains(err.Error(), "explicit credential choice") { - t.Fatalf("endpoint edit forwarded old credential: %v", err) - } - } -} - -func TestProviderConfigurationUnverifiedAndAuthenticationFailures(t *testing.T) { - for _, outcome := range []string{"empty", "404", "transport", "401", "403", "missing environment"} { - t.Run(outcome, func(t *testing.T) { - s := customProviderService(t) - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - switch outcome { - case "empty": - return nil, nil - case "transport": - return nil, errors.New("private-fixture-key inside URL error") - case "missing environment": - t.Fatal("attempted request with absent environment credential") - } - return nil, &llm.HTTPError{Status: outcome + " failure", Body: "private-fixture-key echoed by upstream"} - } - p := customProviderParams(t, s) - if outcome == "missing environment" { - t.Setenv("WHIP_MISSING_PROVIDER_TEST_KEY", "") - p.Credential = protocol.ProviderCredential{Mode: "environment", EnvironmentVariable: "WHIP_MISSING_PROVIDER_TEST_KEY"} - } - if _, err := s.CreateProvider(t.Context(), p); err == nil || strings.Contains(err.Error(), "private-fixture-key") { - t.Fatalf("normal save should fail safely: %v", err) - } - p.AllowUnverified = true - p.ManualModel = &protocol.ProviderManualModel{Alias: "custom-test/exact-model", ID: "exact-model"} - result, err := s.CreateProvider(t.Context(), p) - if outcome == "401" || outcome == "403" { - if err == nil { - t.Fatal("explicit save bypassed a known authentication rejection") - } - if _, readErr := s.ReadProvider(p.Provider); readErr == nil { - t.Fatal("rejected credentials were persisted") - } - return - } - if err != nil || result.Discovery.Status != "unverified" || len(result.Models) != 1 { - t.Fatalf("unverified save: %+v %v", result, err) - } - if outcome == "missing environment" && (result.Credential.Available == nil || *result.Credential.Available) { - t.Fatal("missing environment credential is ready") - } - }) - } -} - -func TestProviderConfigurationValidationAndRemoval(t *testing.T) { - s := customProviderService(t) - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return []llm.ModelInfo{{ID: "m"}}, nil } - p := customProviderParams(t, s) - for _, id := range []string{"inference-net", "inference", "openrouter", "openai-codex", "../escape", "Invalid ID"} { - p.Provider = id - if _, err := s.CreateProvider(t.Context(), p); err == nil { - t.Fatalf("accepted ID %q", id) - } - } - p.Provider = "custom-test" - for _, endpoint := range []string{"https://key:secret@example.test/v1", "https://example.test/v1?secret=value", "https://example.test/v1#fragment", "file:///tmp/model", "https://example.test/v1/chat/completions"} { - p.Definition.BaseURL = endpoint - if _, err := s.CreateProvider(t.Context(), p); err == nil { - t.Fatalf("accepted endpoint %q", endpoint) - } - } - p.Definition.BaseURL = "https://example.test/v1" - for _, key := range []string{"!touch /tmp/whip-test-must-not-execute", "$WHIP_KEY", "${WHIP_KEY}"} { - p.Credential.Key = key - if _, err := s.CreateProvider(t.Context(), p); err == nil { - t.Fatalf("accepted reference as a literal key %q", key) - } - } - p.Credential.Key = "private-fixture-key" - result, err := s.CreateProvider(t.Context(), p) - if err != nil { - t.Fatal(err) - } - _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: "inference-net", Revision: result.Revision}) - if err == nil { - t.Fatal("removed a built-in provider") - } - _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: p.Revision}) - if !errors.Is(err, config.ErrRevisionConflict) { - t.Fatalf("stale removal: %v", err) - } - removed, err := s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: result.Revision}) - if err != nil || removed.Revision == result.Revision { - t.Fatalf("remove: %+v %v", removed, err) - } - if _, err := s.ReadProvider(p.Provider); err == nil { - t.Fatal("removed provider remains") - } - if _, exists := config.LoadCatalogs()[p.Provider]; exists { - t.Fatal("removed provider's catalog remains") - } -} - -func TestProviderConfigurationInvalidCreateLeavesSettingsUntouched(t *testing.T) { - s := customProviderService(t) - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - t.Error("invalid configuration reached model discovery") - return nil, errors.New("unexpected discovery") - } - valid := customProviderParams(t, s) - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - for _, test := range []struct { - name string - change func(*protocol.ProviderCreateParams) - }{ - {"missing display name", func(p *protocol.ProviderCreateParams) { p.Definition.Name = " " }}, - {"unsupported API", func(p *protocol.ProviderCreateParams) { p.Definition.API = "anthropic" }}, - {"keep without saved credential", func(p *protocol.ProviderCreateParams) { p.Credential = protocol.ProviderCredential{Mode: "keep"} }}, - {"empty key", func(p *protocol.ProviderCreateParams) { p.Credential.Key = " " }}, - {"header injection", func(p *protocol.ProviderCreateParams) { p.Credential.Key = "key\r\nInjected: header" }}, - {"invalid environment name", func(p *protocol.ProviderCreateParams) { - p.Credential = protocol.ProviderCredential{Mode: "environment", EnvironmentVariable: "NOT-A-VARIABLE"} - }}, - {"credential with no auth", func(p *protocol.ProviderCreateParams) { p.Credential.Mode = "none" }}, - {"unknown auth mode", func(p *protocol.ProviderCreateParams) { p.Credential.Mode = "custom" }}, - {"ambiguous model ID", func(p *protocol.ProviderCreateParams) { - p.ManualModel = &protocol.ProviderManualModel{Alias: "custom/model", ID: " model "} - }}, - {"negative model limits", func(p *protocol.ProviderCreateParams) { - p.ManualModel = &protocol.ProviderManualModel{Alias: "custom/model", ID: "model", Context: -1} - }}, - } { - t.Run(test.name, func(t *testing.T) { - params := valid - test.change(¶ms) - if _, err := s.CreateProvider(t.Context(), params); err == nil { - t.Fatal("invalid connection accepted") - } - after, err := s.ReadConfiguration() - if err != nil || !reflect.DeepEqual(after, before) { - t.Fatalf("failed create changed persisted configuration: %+v %v", after, err) - } - if _, err := s.ReadProvider(valid.Provider); err == nil { - t.Fatal("failed create left a partial connection") - } - }) - } -} - -func TestProviderOperationsFailClosedForMalformedHostConfiguration(t *testing.T) { - s := customProviderService(t) - params := customProviderParams(t, s) - directory, err := config.Dir() - if err != nil { - t.Fatal(err) - } - path := filepath.Join(directory, "config.json") - if err := os.WriteFile(path, []byte("{not valid configuration"), 0o600); err != nil { - t.Fatal(err) - } - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - t.Error("unreadable configuration initiated discovery") - return nil, errors.New("unexpected request") - } - s.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { - t.Error("unreadable configuration initiated sign-in") - return openaiauth.Credentials{}, errors.New("unexpected authorization") - } - for _, test := range []struct { - name string - call func() error - }{ - {"configuration", func() error { _, err := s.ReadConfiguration(); return err }}, - {"editable provider", func() error { _, err := s.ReadProvider("openrouter"); return err }}, - {"account status", func() error { _, err := s.ProviderStatus(openaiauth.Provider); return err }}, - {"OpenAI sign-in", func() error { _, err := s.BeginProviderLogin(openaiauth.Provider); return err }}, - {"Inference sign-in", func() error { _, err := s.BeginLogin(); return err }}, - {"create", func() error { _, err := s.CreateProvider(t.Context(), params); return err }}, - {"model client", func() error { - _, err := s.ModelClient(config.Provider{BaseURL: "https://example.test/v1", APIKey: "private-fixture-key"}) - return err - }}, - {"catalog refresh", func() error { return s.refreshCatalog(t.Context(), "openrouter", config.Provider{}) }}, - } { - t.Run(test.name, func(t *testing.T) { - if err := test.call(); err == nil { - t.Fatal("operation silently accepted malformed host configuration") - } - }) - } - if len(s.Catalogs()) != 0 || len(s.ListLogins().Flows) != 0 { - t.Fatal("unreadable configuration exposed routes or admitted authorization") - } - if err := os.Remove(path); err != nil { - t.Fatal(err) - } - if recovered, err := s.ReadConfiguration(); err != nil || recovered.Revision != params.Revision { - t.Fatalf("repaired configuration requires a daemon restart: %+v %v", recovered, err) - } -} - -func TestProviderConfigurationConcurrentEditAndCancellation(t *testing.T) { - for _, action := range []string{"edit", "cancel"} { - t.Run(action, func(t *testing.T) { - s := customProviderService(t) - ctx, cancel := context.WithCancel(t.Context()) - defer cancel() - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - if action == "cancel" { - cancel() - } else { - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { cfg.Theme = "light"; return nil }) - if err != nil { - t.Fatal(err) - } - } - return []llm.ModelInfo{{ID: "fixture"}}, nil - } - p := customProviderParams(t, s) - _, err := s.CreateProvider(ctx, p) - if action == "edit" && !errors.Is(err, config.ErrRevisionConflict) || action == "cancel" && !errors.Is(err, context.Canceled) { - t.Fatalf("unexpected failure: %v", err) - } - cfg, _ := config.Load() - if _, exists := cfg.Providers[p.Provider]; exists { - t.Fatal("interrupted create committed configuration") - } - if action == "edit" && cfg.Theme != "light" { - t.Fatal("concurrent config change lost") - } - }) - } -} - -func TestProviderConfigurationManualAliasOwnershipAndRemovalBlockers(t *testing.T) { - s := customProviderService(t) - s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return []llm.ModelInfo{{ID: "fixture"}}, nil - } - p := customProviderParams(t, s) - p.ManualModel = &protocol.ProviderManualModel{Alias: "kimi-k3", ID: "other-model"} - if _, err := s.CreateProvider(t.Context(), p); err == nil { - t.Fatal("create overwrote a configured model alias") - } - p.ManualModel = &protocol.ProviderManualModel{Alias: "custom-test/fixture", ID: "fixture", Context: 8192, MaxOutput: 2048} - created, err := s.CreateProvider(t.Context(), p) - if err != nil { - t.Fatal(err) - } - if len(created.RemovalBlockers) != 1 || !strings.Contains(created.RemovalBlockers[0], "custom-test/fixture") { - t.Fatalf("missing alias blocker: %+v", created.RemovalBlockers) - } - if _, err := s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: created.Revision}); err == nil { - t.Fatal("removed provider referenced by alias") - } - updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: p.Provider, Revision: created.Revision, ManualModel: &protocol.ProviderManualModel{Alias: p.ManualModel.Alias, ID: "fixture", Context: 16384, MaxOutput: 4096}}) - if err != nil || len(updated.Models) != 1 || updated.Models[0].Context != 16384 { - t.Fatalf("model limit update: %+v %v", updated, err) - } - _, err = s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: p.Provider, Revision: updated.Revision, ManualModel: &protocol.ProviderManualModel{Alias: p.ManualModel.Alias, ID: "different-model"}}) - if err == nil { - t.Fatal("update replaced an alias with a different model") - } - _, _, err = config.UpdateVersioned(updated.Revision, func(cfg *config.Config) error { - cfg.DefaultProvider, cfg.CompactProvider = p.Provider, p.Provider - return nil - }) - if err != nil { - t.Fatal(err) - } - read, _ := s.ReadProvider(p.Provider) - if len(read.RemovalBlockers) != 3 { - t.Fatalf("default/compaction references missing: %v", read.RemovalBlockers) - } -} - -func TestProviderConfigurationBuiltinsAndCredentialReplacement(t *testing.T) { - s := customProviderService(t) - t.Setenv("OPENROUTER_API_KEY", "private-environment-key") - read, err := s.ReadProvider("openrouter") - if err != nil || read.Custom || read.Credential.Mode != "environment" || read.Definition.BaseURL != config.OpenRouterBaseURL { - t.Fatalf("builtin read: %+v %v", read, err) - } - s.validate = func(ctx context.Context, endpoint, key string) ([]llm.ModelInfo, error) { - if endpoint != config.OpenRouterBaseURL || key != "private-new-key" { - t.Fatal("unexpected built-in route or credential") - } - return []llm.ModelInfo{{ID: "fixture", SupportsTools: new(true), OutputModalities: []string{"text"}}}, nil - } - updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: "openrouter", Revision: read.Revision, Credential: &protocol.ProviderCredential{Mode: "api_key", Key: "private-new-key"}}) - if err != nil || updated.Credential.Mode != "api_key" { - t.Fatalf("builtin edit: %+v %v", updated, err) - } - body, _ := json.Marshal(updated) - if strings.Contains(string(body), "private-") { - t.Fatal("save response exposed a credential") - } - cfg, _ := config.Load() - if cfg.Providers["openrouter"].APIKeyEnv != "" || cfg.Providers["openrouter"].APIKey != "private-new-key" { - t.Fatal("replacement left an environment fallback") - } - _, err = s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: "openrouter", Revision: updated.Revision, BaseURL: new("https://other.test/v1"), Credential: &protocol.ProviderCredential{Mode: "none"}}) - if err == nil { - t.Fatal("edited a built-in endpoint") - } -} - -func TestProviderConfigurationLastProviderRemovalPreservesRecoveryGuard(t *testing.T) { - s := customProviderService(t) - _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers = map[string]config.Provider{"only": {Name: "Only provider", BaseURL: "http://localhost:1234/v1", Auth: "none"}} - cfg.Models = map[string]config.Model{} - cfg.DefaultModel, cfg.DefaultProvider, cfg.CompactModel, cfg.CompactProvider = "", "", "", "" - return nil - }) - if err != nil { - t.Fatal(err) - } - _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: "only", Revision: revision}) - if err == nil || !strings.Contains(err.Error(), "Add another connection") { - t.Fatalf("missing last-provider guidance: %v", err) - } - cfg, after, err := config.ReadVersioned() - if err != nil || after != revision || len(cfg.Providers) != 1 { - t.Fatal("last-provider removal changed protected configuration") - } -} - func TestProviderConfigurationHostRPCAndSecretContracts(t *testing.T) { s := customProviderService(t) server := &Server{providers: s} @@ -497,39 +70,3 @@ func TestProviderConfigurationHostRPCAndSecretContracts(t *testing.T) { t.Fatalf("invalid request was not safely rejected: %+v", rpcErr) } } - -func TestProviderManualModelClearsLegacyLimitAndPreservesOtherFields(t *testing.T) { - cfg := &config.Config{Models: map[string]config.Model{ - "alias": {Name: "Human name", ID: "model", Providers: []string{"custom"}, Context: 4096, MaxTokens: 4096, MaxOut: 1024, Vision: true}, - "shared": {ID: "model", Providers: []string{"custom", "other"}, Context: 4096}, - }} - if err := applyManualProviderModel(cfg, "custom", &protocol.ProviderManualModel{Alias: "alias", ID: "model"}, false); err != nil { - t.Fatal(err) - } - model := cfg.Models["alias"] - if model.Context != 0 || model.MaxTokens != 0 || model.MaxOut != 0 || model.Name != "Human name" || !model.Vision { - t.Fatalf("model metadata was lost or legacy limit survived: %+v", model) - } - if err := applyManualProviderModel(cfg, "custom", &protocol.ProviderManualModel{Alias: "shared", ID: "model", Context: 8192}, false); err == nil || cfg.Models["shared"].Context != 4096 { - t.Fatal("manual model update edited a shared alias") - } -} - -func TestProviderConfigurationRedactsInvalidFileAuthoredEndpoint(t *testing.T) { - s := customProviderService(t) - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["unsafe-old-route"] = config.Provider{Name: "Old connection", BaseURL: "https://user:private-userinfo@example.test/v1?key=private-query#private-fragment", APIKey: "private-literal-key"} - return nil - }) - if err != nil { - t.Fatal(err) - } - read, err := s.ReadProvider("unsafe-old-route") - if err != nil { - t.Fatal(err) - } - encoded, _ := json.Marshal(read) - if strings.Contains(string(encoded), "private-") || read.Definition.BaseURL != "https://example.test/v1" || read.Credential.Available == nil || *read.Credential.Available { - t.Fatalf("unsafe editable metadata: %s", encoded) - } -} diff --git a/internal/daemon/provider_connections_test.go b/internal/daemon/provider_connections_test.go index d87e3038a..0450a89a8 100644 --- a/internal/daemon/provider_connections_test.go +++ b/internal/daemon/provider_connections_test.go @@ -1,16 +1,9 @@ package daemon import ( - "context" "encoding/json" - "errors" - "io" "net/http" "net/http/httptest" - "os" - "path/filepath" - "reflect" - "slices" "strings" "sync" "sync/atomic" @@ -19,94 +12,21 @@ import ( "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/openaiauth" - "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" ) -func providerConnectionsFixture(t *testing.T) *ProviderService { +func providerConnectionsFixture(t *testing.T) *providersvc.ProviderService { t.Helper() t.Setenv("WHIPCODE_HOME", t.TempDir()) t.Setenv("HOME", t.TempDir()) t.Setenv(config.InferenceNetEnvVar, "") t.Setenv(config.OpenRouterEnvVar, "") - service := NewProviderService(t.Context(), "connections") + service := providersvc.NewProviderService(t.Context(), "connections") t.Cleanup(service.Close) return service } -func providerEntry(t *testing.T, service *ProviderService, id string) protocol.ProviderEntry { - t.Helper() - list, err := service.ListProviders() - if err != nil { - t.Fatal(err) - } - for _, entry := range list.Providers { - if entry.ID == id { - return entry - } - } - t.Fatalf("missing provider %q", id) - return protocol.ProviderEntry{} -} - -func TestProviderInventoryReportsWinningSourceWithoutExecutingSecrets(t *testing.T) { - service := providerConnectionsFixture(t) - t.Setenv(config.OpenRouterEnvVar, "private-environment-key") - marker := filepath.Join(t.TempDir(), "executed") - cfg, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["command"] = config.Provider{BaseURL: "https://example.test/v1", APIKey: "!touch " + marker} - cfg.Providers["custom"] = config.Provider{Name: "Custom", BaseURL: "https://example.test/v1", APIKey: "private-saved-key"} - cfg.Providers["bad-url"] = config.Provider{BaseURL: "not-a-url", APIKey: "private-saved-key"} - return nil - }) - if err != nil { - t.Fatal(err) - } - before, err := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) - if err != nil { - t.Fatal(err) - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - t.Error("inventory made an upstream request") - return nil, nil - } - list, err := service.ListProviders() - if err != nil { - t.Fatal(err) - } - encoded, err := json.Marshal(list) - if err != nil || strings.Contains(string(encoded), "private-") { - t.Fatal("inventory exposed a credential") - } - for id, want := range map[string]struct { - source, state string - available bool - }{ - "inference-net": {"environment", "key_required", false}, - "openrouter": {"environment", "connected", true}, - "custom": {"literal", "connected", true}, - "command": {"command", "unchecked", false}, - "bad-url": {"literal", "configuration_error", false}, - } { - entry := providerEntry(t, service, id) - if entry.Status.KeySource != want.source || entry.Status.AuthState != want.state || entry.Status.Available == nil || *entry.Status.Available != want.available { - t.Fatalf("%s status = %+v", id, entry.Status) - } - } - if _, err := os.Stat(marker); !errors.Is(err, os.ErrNotExist) { - t.Fatal("inventory executed a secret command") - } - after, _ := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) - if string(before) != string(after) { - t.Fatal("inventory changed saved configuration") - } - if _, ok := cfg.Providers["openrouter"]; ok { - t.Fatal("discovery persisted") - } -} - func TestProviderCatalogRefreshIsExplicitAndRetainsLastGoodModels(t *testing.T) { service := providerConnectionsFixture(t) var requests atomic.Int32 @@ -149,271 +69,6 @@ func TestProviderCatalogRefreshIsExplicitAndRetainsLastGoodModels(t *testing.T) } } -func TestProviderConnectPreservesCustomEndpointAndDefaults(t *testing.T) { - service := providerConnectionsFixture(t) - _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["openrouter"] = config.Provider{Name: "Proxy", BaseURL: "https://proxy.test/v1", API: "openai-completions", APIKeyEnv: "PROXY_TEST_KEY"} - cfg.DisabledProviders = []string{"openrouter", "unrelated"} - return nil - }) - if err != nil { - t.Fatal(err) - } - before, _ := config.Load() - service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { - if endpoint != "https://proxy.test/v1" || key != "private-new-key" { - t.Fatal("setup replaced the configured endpoint or key") - } - return []llm.ModelInfo{{ID: "fixture-model"}}, nil - } - if _, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: revision, Provider: "openrouter", Key: "private-new-key"}); err != nil { - t.Fatal(err) - } - after, _ := config.Load() - if after.DefaultModel != before.DefaultModel || after.DefaultProvider != before.DefaultProvider || !reflect.DeepEqual(after.Models, before.Models) { - t.Fatal("connect changed model defaults or aliases") - } - if after.Providers["openrouter"].Name != "Proxy" || after.Providers["openrouter"].APIKeyEnv != "" || !reflect.DeepEqual(after.DisabledProviders, []string{"unrelated"}) { - t.Fatal("connect changed route metadata or unrelated disabled entries") - } - if _, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: revision, Provider: "openrouter", Key: "private-other-key"}); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatalf("stale setup = %v", err) - } -} - -func TestProviderDisconnectRestoresDefaultSetup(t *testing.T) { - for _, environment := range []string{"", "private-environment-key"} { - t.Run(map[bool]string{true: "environment", false: "empty"}[environment != ""], func(t *testing.T) { - service := providerConnectionsFixture(t) - t.Setenv(config.OpenRouterEnvVar, environment) - before, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["openrouter"] = config.Provider{BaseURL: config.OpenRouterBaseURL, APIKey: "private-saved-key"} - cfg.DisabledProviders = []string{"openrouter", "unrelated"} - return nil - }) - if err != nil { - t.Fatal(err) - } - if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, Models: []config.ModelInfoLite{{ID: "fixture"}}}); err != nil { - t.Fatal(err) - } - status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}) - if err != nil || status.Disabled || status.Available == nil || *status.Available != (environment != "") { - t.Fatalf("disconnect = %+v, %v", status, err) - } - cfg, err := config.Load() - if err != nil || cfg.Providers["openrouter"].APIKey != "" || cfg.Providers["openrouter"].APIKeyEnv != config.OpenRouterEnvVar || cfg.DefaultModel != before.DefaultModel || !reflect.DeepEqual(cfg.Models, before.Models) || !reflect.DeepEqual(cfg.DisabledProviders, []string{"unrelated"}) { - t.Fatal("disconnect did not restore setup while preserving unrelated config") - } - if _, exists := config.LoadCatalogs()["openrouter"]; exists { - t.Fatal("disconnect retained cache") - } - restarted := NewProviderService(t.Context(), "restarted") - t.Cleanup(restarted.Close) - reloaded := providerEntry(t, restarted, "openrouter").Status - if reloaded.Disabled || reloaded.Available == nil || *reloaded.Available != (environment != "") { - t.Fatal("restart changed reset state") - } - if _, err := restarted.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatal("stale disconnect accepted") - } - }) - } -} - -func TestProviderDisconnectClearsPreviousAccountBehindAnAPIKey(t *testing.T) { - service := providerConnectionsFixture(t) - if err := inferencenet.SaveAuth(inferencenet.Auth{MachineKey: "old-account-key", TeamName: "Old team"}); err != nil { - t.Fatal(err) - } - _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: config.InferenceNetBaseURL, APIKey: "saved-key"} - return nil - }) - if err != nil { - t.Fatal(err) - } - status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: config.InferenceNetProvider, Revision: revision}) - if err != nil || status.Disabled || status.Available == nil || *status.Available { - t.Fatalf("disconnect = %+v, %v", status, err) - } - auth, err := inferencenet.LoadAuth() - if err != nil || auth != (inferencenet.Auth{}) { - t.Fatal("old account survived disconnect") - } -} - -func TestProviderEnvironmentDisablePreservesKeysAndInterruptsLogin(t *testing.T) { - service := providerConnectionsFixture(t) - t.Setenv(config.OpenRouterEnvVar, "private-environment-key") - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - if _, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: before.Revision}); err == nil { - t.Fatal("allowed removing an external credential") - } - ready := make(chan struct{}) - service.openAILogin = func(ctx context.Context, _ func(string, string)) (openaiauth.Credentials, error) { - close(ready) - <-ctx.Done() - return openaiauth.Credentials{}, ctx.Err() - } - flow, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - <-ready - disabled := []string{"openrouter", openaiauth.Provider} - updated, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DisabledProviders: &disabled}) - if err != nil { - t.Fatal(err) - } - if state, _ := service.LoginStatus(flow.FlowID); state.State != "interrupted" { - t.Fatal("disable left login able to reconnect provider") - } - if os.Getenv(config.OpenRouterEnvVar) != "private-environment-key" { - t.Fatal("disable changed environment") - } - if _, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DisabledProviders: new([]string{})}); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatal("stale enable accepted") - } - if _, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: updated.Revision, DisabledProviders: new([]string{})}); err != nil { - t.Fatal(err) - } - if !*providerEntry(t, service, "openrouter").Status.Available { - t.Fatal("enable did not restore environment route") - } -} - -func TestProviderDisabledDuringCatalogFetchCannotRepublishModels(t *testing.T) { - service := providerConnectionsFixture(t) - started, release := make(chan struct{}), make(chan struct{}) - upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - close(started) - <-release - _, _ = w.Write([]byte(`{"data":[{"id":"fixture-model"}]}`)) - })) - t.Cleanup(upstream.Close) - cfg, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["custom"] = config.Provider{BaseURL: upstream.URL, APIKey: "fixture"} - return nil - }) - if err != nil { - t.Fatal(err) - } - done := make(chan error, 1) - go func() { done <- service.refreshCatalog(t.Context(), "custom", cfg.Providers["custom"]) }() - <-started - disabled := []string{"custom"} - _, disableErr := service.UpdateConfiguration(ConfigurationUpdate{Revision: revision, DisabledProviders: &disabled}) - close(release) - if disableErr != nil { - t.Fatal(disableErr) - } - select { - case err := <-done: - if err == nil { - t.Fatal("late catalog was accepted") - } - case <-time.After(3 * time.Second): - t.Fatal("catalog fetch did not finish") - } - if _, exists := service.Catalogs()["custom"]; exists { - t.Fatal("disabled models republished") - } -} - -func TestProviderInferenceLoginPreservesCustomOverride(t *testing.T) { - service := providerConnectionsFixture(t) - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "fixture"} - return nil - }) - if err != nil { - t.Fatal(err) - } - entry := providerEntry(t, service, config.InferenceNetProvider) - if !entry.Custom || slices.Contains(entry.Methods, "login") { - t.Fatal("custom endpoint advertised account login") - } - if _, err := service.BeginLogin(); err == nil { - t.Fatal("account login accepted a custom endpoint") - } -} - -func TestProviderCustomDisconnectLeavesUnrelatedAccountIntact(t *testing.T) { - service := providerConnectionsFixture(t) - auth := inferencenet.Auth{MachineKey: "private-unrelated-machine-key"} - if err := inferencenet.SaveAuth(auth); err != nil { - t.Fatal(err) - } - _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "private-custom-key"} - return nil - }) - if err != nil { - t.Fatal(err) - } - if _, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: config.InferenceNetProvider, Revision: revision}); err != nil { - t.Fatal(err) - } - retained, err := inferencenet.LoadAuth() - if err != nil || retained.MachineKey != auth.MachineKey { - t.Fatal("custom disconnect removed unrelated account") - } -} - -type providerFixtureTransport func(*http.Request) (*http.Response, error) - -func (f providerFixtureTransport) RoundTrip(request *http.Request) (*http.Response, error) { - return f(request) -} - -func TestProviderAccountReplacementCannotRepublishOldCatalog(t *testing.T) { - service := providerConnectionsFixture(t) - if err := inferencenet.SaveAuth(inferencenet.Auth{MachineKey: "private-old-machine-key"}); err != nil { - t.Fatal(err) - } - cfg, err := config.Load() - if err != nil { - t.Fatal(err) - } - started, release := make(chan struct{}), make(chan struct{}) - previous := http.DefaultTransport - http.DefaultTransport = providerFixtureTransport(func(request *http.Request) (*http.Response, error) { - if request.URL.String() != config.InferenceNetBaseURL+"/models" || request.Header.Get("Authorization") != "Bearer private-old-machine-key" { - t.Error("unexpected fixture provider request") - } - close(started) - select { - case <-release: - case <-request.Context().Done(): - return nil, request.Context().Err() - } - return &http.Response{StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(`{"data":[{"id":"old-account-model"}]}`))}, nil - }) - t.Cleanup(func() { http.DefaultTransport = previous }) - done := make(chan error, 1) - go func() { - done <- service.refreshCatalog(t.Context(), config.InferenceNetProvider, cfg.Providers[config.InferenceNetProvider]) - }() - <-started - service.provisionMu.Lock() - err = service.finish(t.Context(), inferencenet.Auth{MachineKey: "private-new-machine-key"}) - service.provisionMu.Unlock() - close(release) - if err != nil { - t.Fatal(err) - } - if err := <-done; err == nil { - t.Fatal("old account catalog was accepted after replacement") - } - if _, exists := config.LoadCatalogs()[config.InferenceNetProvider]; exists { - t.Fatal("old account models survived replacement") - } -} - func TestProviderDisableBlocksRetainedRootChildAndHelperClients(t *testing.T) { service := providerConnectionsFixture(t) var requests atomic.Int32 @@ -480,24 +135,3 @@ func TestProviderDisableBlocksRetainedRootChildAndHelperClients(t *testing.T) { t.Fatal("disabled route was dispatched or automatically retried") } } - -func TestProviderResetLegacyDisabledEnvironmentPreservesSource(t *testing.T) { - service := providerConnectionsFixture(t) - t.Setenv(config.OpenRouterEnvVar, "environment-key") - _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["openrouter"] = config.Provider{BaseURL: config.OpenRouterBaseURL, APIKeyEnv: config.OpenRouterEnvVar} - cfg.DisabledProviders = []string{"openrouter", "unrelated"} - return nil - }) - if err != nil { - t.Fatal(err) - } - status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}) - if err != nil || status.Disabled || status.Available == nil || !*status.Available { - t.Fatalf("reset = %+v, %v", status, err) - } - cfg, err := config.Load() - if err != nil || cfg.Providers["openrouter"].APIKeyEnv != config.OpenRouterEnvVar || os.Getenv(config.OpenRouterEnvVar) != "environment-key" || !reflect.DeepEqual(cfg.DisabledProviders, []string{"unrelated"}) { - t.Fatal("reset changed external credentials or unrelated providers") - } -} diff --git a/internal/daemon/provider_discovery_test.go b/internal/daemon/provider_discovery_test.go index 02d11d6ce..cde9a848a 100644 --- a/internal/daemon/provider_discovery_test.go +++ b/internal/daemon/provider_discovery_test.go @@ -1,130 +1,12 @@ package daemon import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" "testing" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" ) -func TestDiscoveredFileKeyPersistsReferenceAndReachesInference(t *testing.T) { - service := pickerInventoryFixture(t) - filename := filepath.Join(t.TempDir(), "providers.env") - writeKey := func(value string) { - t.Helper() - if err := os.WriteFile(filename, []byte("OPENROUTER_API_KEY="+value+"\n"), 0o600); err != nil { - t.Fatal(err) - } - } - writeKey("fixture-file-key") - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.ProviderKeySources.EnvFiles = []string{filename} - return nil - }) - if err != nil { - t.Fatal(err) - } - before := providerEntry(t, service, "openrouter") - if before.Status.Configured || !*before.Status.Available || before.Status.KeySource != "env_file" { - t.Fatal("read-only inventory did not resolve a file-backed key") - } - list, err := service.DiscoverProviders(t.Context(), "", "") - if err != nil || list.DiscoveryError != "" { - t.Fatalf("discovery: %v %s", err, list.DiscoveryError) - } - entry := providerEntry(t, service, "openrouter") - if !entry.Status.Configured || entry.Status.CredentialPath != filename || entry.Status.EnvironmentVariable != "OPENROUTER_API_KEY" { - t.Fatal("discovery did not persist the named reference and provenance") - } - managed, err := service.ReadProvider("openrouter") - if err != nil || managed.Credential.Mode != "environment" || managed.Credential.CredentialPath != filename { - t.Fatal("management lost the editable named reference") - } - data, err := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) - if err != nil || strings.Contains(string(data), "fixture-file-key") { - t.Fatal("configuration persisted resolved credential material") - } - encoded, err := json.Marshal(list) - if err != nil || strings.Contains(string(encoded), "fixture-file-key") { - t.Fatal("provider inventory exposed resolved credential material") - } - second, err := service.DiscoverProviders(t.Context(), "", "") - if err != nil || second.Revision != list.Revision { - t.Fatal("no-op discovery changed the revision") - } - unchanged, _ := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) - if string(unchanged) != string(data) { - t.Fatal("no-op discovery rewrote configuration") - } - - expectedKey := "fixture-file-key" - var paths []string - previous := http.DefaultTransport - http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { - if r.URL.Host != "openrouter.ai" || r.Header.Get("Authorization") != "Bearer "+expectedKey { - t.Fatal("file credential did not reach the expected provider") - } - paths = append(paths, r.URL.Path) - body := `{"data":{"label":"fixture"}}` - switch r.URL.Path { - case "/api/v1/key": - case "/api/v1/models": - body = `{"data":[{"id":"new-live-model"}]}` - case "/api/v1/chat/completions": - body = "data: {\"choices\":[{\"delta\":{\"content\":\"hello\"}}]}\n\ndata: [DONE]\n\n" - default: - t.Fatal("unexpected provider request") - } - return &http.Response{StatusCode: http.StatusOK, Status: "200 OK", Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil - }) - t.Cleanup(func() { http.DefaultTransport = previous }) - for _, key := range []string{"fixture-file-key", "fixture-rotated-key"} { - writeKey(key) - expectedKey = key - // A new owner/constructor rereads references after a restart or reload. - restarted := NewProviderService(t.Context(), key) - cfg, loadErr := config.Load() - if loadErr != nil { - t.Fatal(loadErr) - } - provider := cfg.Providers["openrouter"] - if err := restarted.refreshCatalog(t.Context(), "openrouter", provider); err != nil { - t.Fatal(err) - } - catalog := restarted.Catalogs()["openrouter"] - if len(catalog.Models) != 1 || catalog.Models[0].ID != "new-live-model" { - t.Fatal("bundled catalog replaced live membership") - } - client, err := restarted.ModelClient(provider) - if err != nil { - t.Fatal(err) - } - message, _, err := client.Stream(t.Context(), llm.Request{Model: "new-live-model"}, nil, nil, nil) - restarted.Close() - if err != nil || message.Content != "hello" { - t.Fatalf("file-key inference: %v", err) - } - } - if len(paths) != 6 { - t.Fatal("expected authenticated discovery followed by inference on each construction") - } - if err := os.Remove(filename); err != nil { - t.Fatal(err) - } - entry = providerEntry(t, service, "openrouter") - if !entry.Status.Configured || *entry.Status.Available || len(entry.Status.Warnings) == 0 { - t.Fatal("removed key source must retain its route with recovery information") - } -} - func TestProviderDiscoveryRPCUsesHostSourcesAndPreservesOptOut(t *testing.T) { _, client, root, _ := providerBehaviorFixture(t) for _, preset := range config.ProviderPresets() { @@ -155,29 +37,3 @@ func TestProviderDiscoveryRPCUsesHostSourcesAndPreservesOptOut(t *testing.T) { } t.Fatal("disabled provider disappeared") } - -func TestDiscoveredOpenRouterKeyStillRequiresAuthentication(t *testing.T) { - service := pickerInventoryFixture(t) - t.Setenv("OPENROUTER_API_KEY", "fixture-invalid-key") - if _, err := service.DiscoverProviders(t.Context(), "", ""); err != nil { - t.Fatal(err) - } - previous := http.DefaultTransport - http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { - if r.URL.Path != "/api/v1/key" { - t.Fatal("public catalog fetched before rejecting the credential") - } - return &http.Response{StatusCode: http.StatusUnauthorized, Status: fmt.Sprintf("%d Unauthorized", 401), Body: io.NopCloser(strings.NewReader("fixture-invalid-key"))}, nil - }) - t.Cleanup(func() { http.DefaultTransport = previous }) - cfg, err := config.Load() - if err != nil { - t.Fatal(err) - } - if err := service.refreshCatalog(t.Context(), "openrouter", cfg.Providers["openrouter"]); err == nil || strings.Contains(err.Error(), "fixture-invalid-key") { - t.Fatal("discovered invalid key was accepted or exposed") - } - if len(service.Catalogs()) != 0 { - t.Fatal("failed authentication populated a bundled model catalog") - } -} diff --git a/internal/daemon/provider_list_test.go b/internal/daemon/provider_list_test.go index 603a42454..8d99ac33e 100644 --- a/internal/daemon/provider_list_test.go +++ b/internal/daemon/provider_list_test.go @@ -1,15 +1,13 @@ package daemon import ( - "os" - "path/filepath" - "slices" "testing" "github.com/context-labs/whip/internal/config" + providersvc "github.com/context-labs/whip/internal/provider" ) -func pickerInventoryFixture(t *testing.T) *ProviderService { +func pickerInventoryFixture(t *testing.T) *providersvc.ProviderService { t.Helper() service := providerConnectionsFixture(t) t.Chdir(t.TempDir()) @@ -25,79 +23,3 @@ func pickerInventoryFixture(t *testing.T) *ProviderService { } return service } - -func TestProviderListPresetMetadataAndEndpointCollisions(t *testing.T) { - service := pickerInventoryFixture(t) - list, err := service.ListProviders() - if err != nil || len(list.Providers) != 11 { - t.Fatalf("inventory: %v", err) - } - for _, id := range []string{"openai", "openai-codex"} { - entry := providerEntry(t, service, id) - if entry.Family != "openai" || entry.Category != "popular" { - t.Fatal("OpenAI execution routes omitted their display family") - } - } - entry := providerEntry(t, service, "groq") - if entry.Category != "providers" || entry.KeyURL == "" || entry.Custom || !slices.Equal(entry.Methods, []string{"api_key"}) { - t.Fatal("preset omitted its single-key presentation metadata") - } - _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers["openai"] = config.Provider{Name: "Existing proxy", BaseURL: "https://proxy.example/v1", APIKey: "private-proxy-key"} - return nil - }) - if err != nil { - t.Fatal(err) - } - entry = providerEntry(t, service, "openai") - if !entry.Custom || entry.Family != "" || entry.KeyURL != "" || entry.Name != "Existing proxy" { - t.Fatal("new preset hid the saved custom route") - } -} - -func TestProviderListIgnoresOpenCodeKeys(t *testing.T) { - service := pickerInventoryFixture(t) - directory := filepath.Join(os.Getenv("XDG_DATA_HOME"), "opencode") - if err := os.MkdirAll(directory, 0o700); err != nil { - t.Fatal(err) - } - filename := filepath.Join(directory, "auth.json") - auth := []byte(`{"groq":{"type":"api","key":"private-opencode-fixture"}}`) - if err := os.WriteFile(filename, auth, 0o600); err != nil { - t.Fatal(err) - } - entry := providerEntry(t, service, "groq") - if entry.Status.Configured || entry.Status.Available == nil || *entry.Status.Available { - t.Fatal("OpenCode credentials created an available connection") - } - if _, err := service.DiscoverProviders(t.Context(), "", ""); err != nil { - t.Fatal(err) - } - entry = providerEntry(t, service, "groq") - if entry.Status.Configured || *entry.Status.Available { - t.Fatal("discovery imported OpenCode credentials") - } - unchanged, err := os.ReadFile(filename) - if err != nil || string(unchanged) != string(auth) { - t.Fatal("Whip modified OpenCode credentials") - } -} - -func TestProviderListEnvironmentAliasesAndOpenAIRouting(t *testing.T) { - service := pickerInventoryFixture(t) - t.Setenv("DEEPINFRA_TOKEN", "private-alias-fixture") - t.Setenv("OPENAI_API_KEY", "private-openai-fixture") - t.Setenv("OPENAI_BASE_URL", "https://proxy.example/v1") - entry := providerEntry(t, service, "deepinfra") - if entry.Status.EnvironmentVariable != "DEEPINFRA_TOKEN" || entry.Status.Available == nil || !*entry.Status.Available { - t.Fatal("DeepInfra alias not detected") - } - entry = providerEntry(t, service, "openai") - if entry.Status.Available == nil || *entry.Status.Available || slices.Contains(entry.Methods, "environment") { - t.Fatal("OpenAI key was offered for a conflicting destination") - } - entry = providerEntry(t, service, "openai-codex") - if entry.Status.Available != nil && *entry.Status.Available { - t.Fatal("API key was interpreted as ChatGPT subscription credentials") - } -} diff --git a/internal/daemon/provider_model_test.go b/internal/daemon/provider_model_test.go index 66537db51..0992cef14 100644 --- a/internal/daemon/provider_model_test.go +++ b/internal/daemon/provider_model_test.go @@ -1,482 +1,9 @@ package daemon import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net" "net/http" - "os" - "path/filepath" - "reflect" - "strings" - "testing" - "time" - - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/openaiauth" - "github.com/context-labs/whip/internal/protocol" ) -func TestPresetDiscoveryFallbackAndPublicCatalog(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "fixture") - defer service.Close() - for _, preset := range config.ProviderPresets() { - if preset.ID == openaiauth.Provider { - continue - } - t.Run(preset.ID, func(t *testing.T) { - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &net.DNSError{Err: "network unavailable private-key"} - } - models, discovery, err := service.discoverProviderModels(t.Context(), preset.ID, preset.Provider, "fake-key") - if err != nil || len(models) == 0 || discovery.Status != "unverified" || !strings.Contains(discovery.Message, "bundled") || strings.Contains(discovery.Message, "private-key") { - t.Fatalf("fallback: %+v %+v %v", models, discovery, err) - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return []llm.ModelInfo{{ID: models[0].ID}}, nil - } - _, discovery, err = service.discoverProviderModels(t.Context(), preset.ID, preset.Provider, "fake-key") - want := "loaded" - if preset.ID == "deepinfra" { - want = "unverified" - } - if err != nil || discovery.Status != want { - t.Fatalf("loaded: %+v %v", discovery, err) - } - }) - } -} - type catalogTransport func(*http.Request) (*http.Response, error) func (f catalogTransport) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } - -func TestOpenRouterSetupAuthenticatesBeforeSavingKey(t *testing.T) { - for _, status := range []int{http.StatusUnauthorized, http.StatusForbidden, http.StatusOK} { - t.Run(http.StatusText(status), func(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - cfg := config.Default() - cfg.UpsertOpenRouter("previous-key", false) - if err := cfg.Save(); err != nil { - t.Fatal(err) - } - service := NewProviderService(t.Context(), "auth-fixture") - defer service.Close() - var paths []string - previous := http.DefaultTransport - http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { - if r.URL.Host != "openrouter.ai" || r.Header.Get("Authorization") != "Bearer submitted-key" { - t.Fatal("incorrect authentication destination or credential") - } - paths = append(paths, r.URL.Path) - code, body := http.StatusOK, `{"data":[{"id":"z-ai/glm-5.3"}]}` - switch r.URL.Path { - case "/api/v1/key": - if r.Method != http.MethodGet { - t.Fatal("credential validation must be read-only") - } - code, body = status, `{"data":{"label":"redacted"}}` - if status != http.StatusOK { - body = `{"error":{"message":"Missing Authentication header submitted-key"}}` - } - case "/api/v1/models": - // This public endpoint succeeds even when the key is invalid. - case "/api/v1/chat/completions": - body = "data: {\"choices\":[{\"delta\":{\"content\":\"hello\"}}]}\n\ndata: [DONE]\n\n" - default: - t.Fatal("unexpected provider request") - } - return &http.Response{StatusCode: code, Status: fmt.Sprintf("%d %s", code, http.StatusText(code)), Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil - }) - t.Cleanup(func() { http.DefaultTransport = previous }) - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - result, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "submitted-key"}) - if status != http.StatusOK { - if err == nil || !strings.Contains(err.Error(), "API key") || strings.Contains(err.Error(), "submitted-key") { - t.Fatalf("invalid key accepted or exposed: %v", err) - } - after, readErr := service.ReadConfiguration() - if readErr != nil || after.Revision != before.Revision || len(config.LoadCatalogs()) != 0 { - t.Fatal("rejected credential changed configuration or cached the public catalog") - } - if strings.Join(paths, ",") != "/api/v1/key" { - t.Fatalf("invalid key reached model discovery: %v", paths) - } - return - } - if err != nil || result.Discovery == nil || result.Discovery.ModelCount != 1 || result.Discovery.Status != "loaded" { - t.Fatalf("valid key did not connect: %+v %v", result.Discovery, err) - } - cfg, err = config.Load() - if err != nil { - t.Fatal(err) - } - client, err := service.ModelClient(cfg.Providers["openrouter"]) - if err != nil { - t.Fatal(err) - } - message, _, err := client.Stream(t.Context(), llm.Request{Model: "z-ai/glm-5.3"}, nil, nil, nil) - if err != nil || message.Content != "hello" || strings.Join(paths, ",") != "/api/v1/key,/api/v1/models,/api/v1/chat/completions" { - t.Fatalf("saved credential did not reach inference: %v %v", paths, err) - } - }) - } -} - -func TestProviderValidationKeepsCustomAndOtherRoutesOnModels(t *testing.T) { - previous := http.DefaultTransport - t.Cleanup(func() { http.DefaultTransport = previous }) - for _, baseURL := range []string{ - "https://openrouter.ai/custom/v1", - "https://openrouter.ai.example.test/api/v1", - "https://api.cerebras.ai/v1", - } { - t.Run(baseURL, func(t *testing.T) { - calls := 0 - http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { - calls++ - if r.URL.String() != baseURL+"/models" || r.Method != http.MethodGet || r.Header.Get("Authorization") != "Bearer fixture-key" { - t.Fatal("route used an unrelated credential check") - } - return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(`{"data":[{"id":"chat-model"}]}`))}, nil - }) - models, err := validateProviderModels(t.Context(), baseURL, "fixture-key") - if err != nil || len(models) != 1 || calls != 1 { - t.Fatalf("model discovery changed: %v (%d requests)", err, calls) - } - }) - } -} - -func TestCerebrasLiveCatalogConnectRefreshAndRestart(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "catalog-fixture") - defer service.Close() - // Cerebras documents this sparse /v1/models shape. Include a future model - // to ensure this test cannot be fixed by just extending the bundled subset. - body := `{"data":[{"id":"gpt-oss-120b"},{"id":"qwen-3.8-27b"},{"id":"future-chat-model"}]}` - calls := 0 - service.validate = func(ctx context.Context, baseURL, key string) ([]llm.ModelInfo, error) { - client := llm.New(baseURL, key) - client.HTTP = &http.Client{Transport: catalogTransport(func(r *http.Request) (*http.Response, error) { - calls++ - if r.Method != http.MethodGet || r.URL.String() != "https://api.cerebras.ai/v1/models" || r.Header.Get("Authorization") != "Bearer fixture-key" { - t.Fatal("incorrect discovery destination or authentication") - } - return &http.Response{ - StatusCode: http.StatusOK, Status: "200 OK", Header: http.Header{}, - Body: io.NopCloser(strings.NewReader(body)), - }, nil - })} - return client.Models(ctx) - } - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - connected, err := service.SetProviderKey(t.Context(), ProviderKeySetup{ - Revision: before.Revision, Provider: "cerebras", Key: "fixture-key", - }) - if err != nil || connected.Discovery == nil || connected.Discovery.ModelCount != 3 || calls != 1 { - t.Fatalf("key connection lost live models: %+v %v (%d requests)", connected, err, calls) - } - want := []string{"gpt-oss-120b", "qwen-3.8-27b", "future-chat-model"} - read := func(refresh bool, wantCalls int) { - t.Helper() - body, err := clientProviderCatalogsFor(t.Context(), service, refresh, "cerebras") - if err != nil { - t.Fatal(err) - } - var result protocol.ProviderCatalogsResult - if err := json.Unmarshal([]byte(body), &result); err != nil { - t.Fatal(err) - } - got := []string{} - for _, model := range result.Catalogs["cerebras"].Models { - got = append(got, model.ID) - } - if !reflect.DeepEqual(got, want) || calls != wantCalls || len(result.Errors) != 0 { - t.Fatalf("picker catalog = %v, errors %v, requests %d (want %v, %d)", got, result.Errors, calls, want, wantCalls) - } - } - read(false, 1) - restarted := NewProviderService(t.Context(), "restarted-catalog-fixture") - defer restarted.Close() - restarted.validate = service.validate - service = restarted - read(false, 1) - // An old binary cached a truncated list moments ago. Normal reads must - // refresh it once, even though its 24-hour TTL has not elapsed. - legacy := config.LoadCatalogs() - old := legacy["cerebras"] - old.DiscoveryVersion = 0 - old.Models = old.Models[:1] - legacy["cerebras"] = old - if err := config.SaveCatalogs(legacy); err != nil { - t.Fatal(err) - } - read(false, 2) - read(false, 2) - body = `{"data":[{"id":"qwen-3.8-27b"},{"id":"newly-released-model"}]}` - want = []string{"qwen-3.8-27b", "newly-released-model"} - read(true, 3) - read(false, 3) - stale := config.LoadCatalogs()["cerebras"] - stale.FetchedAt = time.Now().Add(-25 * time.Hour) - if err := config.UpdateCatalog("cerebras", stale); err != nil { - t.Fatal(err) - } - read(false, 4) - // A transient outage must not replace the last live list with one bundled - // model or mark the old cache as newly fetched. - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &net.DNSError{Err: "offline"} - } - prior := config.LoadCatalogs()["cerebras"] - cfg, _ := config.Load() - if err := service.refreshCatalog(t.Context(), "cerebras", cfg.Providers["cerebras"]); err == nil { - t.Fatal("outage was reported as fresh discovery") - } - if got := config.LoadCatalogs()["cerebras"]; !reflect.DeepEqual(got, prior) { - t.Fatalf("outage replaced live cache: %+v", got) - } -} - -func TestEmptyLiveCatalogDoesNotInsertBundledModels(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "catalog-fixture") - defer service.Close() - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return nil, nil } - provider := config.Provider{BaseURL: "https://api.cerebras.ai/v1", API: "openai-completions"} - models, _, err := service.discoverProviderModels(t.Context(), "cerebras", provider, "fixture-key") - if !errors.Is(err, errNoCompatibleProviderModels) || len(models) != 0 { - t.Fatalf("empty live list was replaced by bundled models: %+v %v", models, err) - } -} - -func TestPresetDiscoveryDoesNotBypassRejectionOrCustomRoute(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "fixture") - defer service.Close() - provider := config.Provider{BaseURL: config.OpenRouterBaseURL, API: "openai-completions"} - for _, status := range []string{"400 Bad Request", "401 Unauthorized", "402 Payment Required", "403 Forbidden", "429 Too Many Requests"} { - t.Run(status, func(t *testing.T) { - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &llm.HTTPError{Status: status} - } - models, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key") - if err == nil || len(models) != 0 { - t.Fatalf("rejection bypassed: %+v %v", models, err) - } - }) - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return nil, context.Canceled } - if _, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key"); !errors.Is(err, context.Canceled) { - t.Fatalf("cancel: %v", err) - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &net.DNSError{Err: "offline"} - } - provider.BaseURL += "/custom" - if _, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key"); err == nil { - t.Fatal("custom endpoint inherited bundled catalog") - } - provider.BaseURL = config.OpenRouterBaseURL - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return []llm.ModelInfo{{ID: "audio", SupportsTools: new(false), OutputModalities: []string{"audio"}}}, nil - } - models, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key") - if !errors.Is(err, errNoCompatibleProviderModels) || len(models) != 0 || !errors.Is(providerValidationError(err), errNoCompatibleProviderModels) { - t.Fatalf("incompatible live catalog was replaced or blamed on the key: %+v %v", models, err) - } -} - -func TestProviderKeySetupPersistsWithHonestFallback(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "fixture") - defer service.Close() - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &net.DNSError{Err: "offline"} - } - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - after, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "groq", Key: "fixture-key"}) - if err != nil || after.Discovery == nil || after.Discovery.Status != "unverified" { - t.Fatalf("setup = %+v %v", after, err) - } - cfg, err := config.Load() - if err != nil || cfg.Providers["groq"].APIKey != "fixture-key" { - t.Fatalf("saved key: %v", err) - } - if len(service.CatalogsFor(cfg)["groq"].Models) == 0 { - t.Fatal("saved key has no model choices") - } - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - return nil, &llm.HTTPError{Status: "401 Unauthorized", Body: "private"} - } - _, err = service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: after.Revision, Provider: "groq", Key: "rejected-key"}) - if err == nil || strings.Contains(err.Error(), "private") { - t.Fatalf("rejection: %v", err) - } - cfg, _ = config.Load() - if cfg.Providers["groq"].APIKey != "fixture-key" { - t.Fatal("rejected key replaced saved key") - } -} - -func TestProviderKeySetupSelectsAvailableEnvironmentAlias(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - t.Setenv("DEEPINFRA_API_KEY", "") - t.Setenv("DEEPINFRA_TOKEN", "fixture-key") - service := NewProviderService(t.Context(), "fixture") - defer service.Close() - service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { - if endpoint != "https://api.deepinfra.com/v1/openai" || key != "fixture-key" { - t.Fatal("wrong environment key or destination") - } - return config.PresetModels("deepinfra"), nil - } - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - _, err = service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "deepinfra", Environment: true}) - if err != nil { - t.Fatal(err) - } - cfg, err := config.Load() - if err != nil || cfg.Providers["deepinfra"].APIKeyEnv != "DEEPINFRA_TOKEN" || cfg.Providers["deepinfra"].APIKey != "" { - t.Fatalf("saved environment reference: %+v %v", cfg.Providers["deepinfra"], err) - } -} - -func TestRefreshCatalogReplacesPriorMembershipWithEmptyLiveResponse(t *testing.T) { - for _, kind := range []string{"empty", "all incompatible"} { - t.Run(kind, func(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - cfg := config.Default() - provider := config.Provider{Name: "Cerebras", BaseURL: "https://api.cerebras.ai/v1", API: "openai-completions", APIKey: "fixture-key"} - cfg.Providers["cerebras"] = provider - if err := cfg.Save(); err != nil { - t.Fatal(err) - } - prior := config.Catalog{FetchedAt: time.Now().Add(-time.Hour), BaseURL: provider.BaseURL, Models: []config.ModelInfoLite{{ID: "old-model"}}} - if err := config.UpdateCatalog("cerebras", prior); err != nil { - t.Fatal(err) - } - service := NewProviderService(t.Context(), "empty-live") - defer service.Close() - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { - if kind == "all incompatible" { - return []llm.ModelInfo{{ID: "non-chat-model", SupportsTools: new(false)}}, nil - } - return []llm.ModelInfo{}, nil - } - err := service.refreshCatalog(t.Context(), "cerebras", provider) - if !errors.Is(err, errNoCompatibleProviderModels) { - t.Fatalf("missing empty selection guidance: %v", err) - } - got, exists := config.LoadCatalogs()["cerebras"] - if !exists || len(got.Models) != 0 || !got.FetchedAt.After(prior.FetchedAt) { - t.Fatal("successful empty response retained prior/bundled membership") - } - if len(service.CatalogsFor(cfg)["cerebras"].Models) != 0 { - t.Fatal("metadata enrichment repopulated an empty catalog") - } - }) - } -} - -func TestSetProviderKeyDoesNotCacheModelsAfterNamedFileRotation(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - t.Setenv("CEREBRAS_API_KEY", "") - filename := filepath.Join(t.TempDir(), "cerebras.key") - if err := os.WriteFile(filename, []byte("first-fixture"), 0o600); err != nil { - t.Fatal(err) - } - cfg := config.Default() - cfg.ProviderKeySources = config.ProviderKeySources{KeyFiles: map[string]string{"CEREBRAS_API_KEY": filename}} - if err := cfg.Save(); err != nil { - t.Fatal(err) - } - service := NewProviderService(t.Context(), "rotate-key") - defer service.Close() - service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { - if endpoint != "https://api.cerebras.ai/v1" || key != "first-fixture" { - t.Fatal("validation used wrong named key") - } - if err := os.WriteFile(filename, []byte("second-fixture"), 0o600); err != nil { - t.Fatal(err) - } - return []llm.ModelInfo{{ID: "old-key-only-model"}}, nil - } - before, err := service.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - connected, err := service.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "cerebras", Environment: true}) - if err != nil { - t.Fatal(err) - } - if connected.Discovery == nil || !strings.Contains(connected.Discovery.Message, "credentials changed") { - t.Fatal("rotated source lacked refresh guidance") - } - if _, exists := config.LoadCatalogs()["cerebras"]; exists { - t.Fatal("published catalog fetched with an obsolete credential") - } - saved, err := config.Load() - if err != nil { - t.Fatal(err) - } - if saved.Providers["cerebras"].APIKeyEnv != "CEREBRAS_API_KEY" || saved.Providers["cerebras"].APIKey != "" { - t.Fatal("lost named reference on rotation") - } - client, err := service.ModelClient(saved.Providers["cerebras"]) - if err != nil || client.APIKey != "second-fixture" { - t.Fatal("new client did not use rotated key") - } -} - -func TestModelClientUsesSuppliedConfigurationSnapshot(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - t.Setenv("SNAPSHOT_FIXTURE_KEY", "") - directory := t.TempDir() - oldFile, newFile := filepath.Join(directory, "old.key"), filepath.Join(directory, "new.key") - if err := os.WriteFile(oldFile, []byte("old-route-fixture"), 0o600); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(newFile, []byte("new-route-fixture"), 0o600); err != nil { - t.Fatal(err) - } - oldCfg := config.Default() - oldCfg.ProviderKeySources.KeyFiles = map[string]string{"SNAPSHOT_FIXTURE_KEY": oldFile} - oldProvider := config.Provider{BaseURL: "https://old.example/v1", APIKeyEnv: "SNAPSHOT_FIXTURE_KEY"} - oldCfg.Providers["custom"] = oldProvider - newer := oldCfg.Snapshot() - newer.ProviderKeySources.KeyFiles["SNAPSHOT_FIXTURE_KEY"] = newFile - newer.Providers["custom"] = config.Provider{BaseURL: "https://new.example/v1", APIKeyEnv: "SNAPSHOT_FIXTURE_KEY"} - if err := newer.Save(); err != nil { - t.Fatal(err) - } - service := NewProviderService(t.Context(), "coherent-config") - defer service.Close() - client, err := service.ModelClient(oldProvider, oldCfg) - if err != nil || client.BaseURL != oldProvider.BaseURL || client.APIKey != "old-route-fixture" { - t.Fatal("old endpoint was combined with newer source configuration") - } - invoked := false - service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { invoked = true; return nil, nil } - if err := service.refreshCatalog(t.Context(), "custom", oldProvider); err == nil || invoked { - t.Fatal("obsolete route reached provider HTTP before the preflight guard") - } -} diff --git a/internal/daemon/provider_openai_test.go b/internal/daemon/provider_openai_test.go index 8a2e9c075..8388bb001 100644 --- a/internal/daemon/provider_openai_test.go +++ b/internal/daemon/provider_openai_test.go @@ -1,19 +1,13 @@ package daemon import ( - "context" "encoding/base64" "encoding/json" - "errors" "net/http" - "os" - "path/filepath" "strings" "testing" "time" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/openaiauth" ) @@ -24,247 +18,6 @@ func openAITestCredentials() openaiauth.Credentials { } } -func TestOpenAILoginFailureCanRetryAndCatalogFailureKeepsLogin(t *testing.T) { - for _, failure := range []string{"authorization", "credential storage"} { - t.Run(failure, func(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "retry") - t.Cleanup(service.Close) - attempts := 0 - service.openAILogin = func(_ context.Context, onCode func(string, string)) (openaiauth.Credentials, error) { - onCode("https://auth.openai.com/codex/device", "expired-code") - attempts++ - if attempts == 1 { - if failure == "authorization" { - return openaiauth.Credentials{}, errors.New("device authorization expired") - } - return openaiauth.Credentials{}, nil - } - return openAITestCredentials(), nil - } - service.refreshModels = func(context.Context, string, config.Provider) error { - return errors.New("upstream failed with private-access-token") - } - first, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - failed := waitProviderState(t, service, first.FlowID, "failed") - if failed.Error == "" || failed.UserCode != "" { - t.Fatalf("failed authorization retained a code or lost its error: %+v", failed) - } - status, err := service.ProviderStatus(openaiauth.Provider) - if err != nil || status.AuthState != "signed_out" { - t.Fatalf("failed login became connected: %+v %v", status, err) - } - retry, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil || retry.FlowID == first.FlowID { - t.Fatalf("failed flow cannot be retried: %+v %v", retry, err) - } - completed := waitProviderState(t, service, retry.FlowID, "succeeded") - if completed.UserCode != "" || !strings.Contains(completed.Error, "Model discovery failed") || strings.Contains(completed.Error, "private-") { - t.Fatalf("discovery failure did not preserve a safe completed login: %+v", completed) - } - status, err = service.ProviderStatus(openaiauth.Provider) - if err != nil || status.AuthState != "connected" || status.Available == nil || !*status.Available { - t.Fatalf("catalog failure invalidated saved login: %+v %v", status, err) - } - }) - } -} - -func TestOpenAICancelledLogoutPreservesCredentials(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "cancelled-logout") - t.Cleanup(service.Close) - if err := service.openAI.Install(t.Context(), service.openAI.Generation(), openAITestCredentials()); err != nil { - t.Fatal(err) - } - ctx, cancel := context.WithCancel(t.Context()) - cancel() - if _, err := service.LogoutProvider(ctx, openaiauth.Provider); !errors.Is(err, context.Canceled) { - t.Fatalf("cancelled logout: %v", err) - } - credentials, err := service.openAI.Snapshot() - if err != nil || credentials.AccessToken != openAITestCredentials().AccessToken { - t.Fatalf("cancelled logout discarded credentials: %v", err) - } -} - -func TestOpenAILoginPreservesConcurrentConfigurationConflict(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "conflict") - t.Cleanup(service.Close) - service.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers[openaiauth.Provider] = config.Provider{API: "openai-completions", BaseURL: "https://custom.example/v1"} - return nil - }) - return openAITestCredentials(), err - } - service.refreshModels = func(context.Context, string, config.Provider) error { - t.Error("discovery ran for a conflicting route") - return errors.New("discovery must not run for a conflicting route") - } - flow, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - failed := waitProviderState(t, service, flow.FlowID, "failed") - if !strings.Contains(failed.Error, "configuration could not be saved") || failed.UserCode != "" { - t.Fatalf("partial setup needs recovery guidance: %+v", failed) - } - status, err := service.ProviderStatus(openaiauth.Provider) - if err != nil || status.AuthState != "configuration_error" || status.Available == nil || *status.Available { - t.Fatalf("conflicting setup reported ready: %+v %v", status, err) - } - configuration, err := config.Load() - if err != nil || configuration.Providers[openaiauth.Provider].BaseURL != "https://custom.example/v1" { - t.Fatalf("sign-in overwrote the concurrent route edit: %v", err) - } - credentials, err := service.openAI.Snapshot() - if err != nil || credentials.AccessToken != openAITestCredentials().AccessToken { - t.Fatalf("partial setup lost completed authorization: %v", err) - } -} - -func TestOpenAILoginRecoveryPersistenceAndLogout(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "first") - service.refreshModels = func(context.Context, string, config.Provider) error { return nil } - t.Cleanup(service.Close) - ready, release := make(chan struct{}), make(chan struct{}) - service.openAILogin = func(ctx context.Context, onCode func(string, string)) (openaiauth.Credentials, error) { - onCode("https://auth.openai.com/codex/device", "public-code") - close(ready) - select { - case <-ctx.Done(): - return openaiauth.Credentials{}, ctx.Err() - case <-release: - return openAITestCredentials(), nil - } - } - first, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - <-ready - second, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil || first.FlowID != second.FlowID || second.UserCode != "public-code" { - t.Fatalf("duplicate login was not recovered: %v", err) - } - if flows := service.ListLogins(); len(flows.Flows) != 1 || flows.Flows[0].Provider != openaiauth.Provider { - t.Fatal("lost acknowledgement cannot be recovered") - } - close(release) - completed := waitProviderState(t, service, first.FlowID, "succeeded") - status, err := service.ProviderStatus(openaiauth.Provider) - if err != nil || !status.Configured || status.AuthState != "connected" || status.Email != "account@example.com" { - t.Fatalf("incorrect connected status: %+v %v", status, err) - } - for _, value := range []any{completed, status, service.ListLogins()} { - data, err := json.Marshal(value) - if err != nil || strings.Contains(string(data), "private-") { - t.Fatal("credentials reached a public response") - } - } - service.Close() - restarted := NewProviderService(t.Context(), "second") - t.Cleanup(restarted.Close) - credentials, err := restarted.openAI.Credentials(t.Context()) - if err != nil || credentials.AccessToken != "private-access-token" { - t.Fatalf("saved login did not survive restart: %v", err) - } - if old, err := restarted.LoginStatus(first.FlowID); err != nil || old.State != "interrupted" { - t.Fatalf("old flow did not report interruption: %v", err) - } - status, err = restarted.LogoutProvider(t.Context(), openaiauth.Provider) - if err != nil || status.AuthState != "signed_out" || !status.Configured { - t.Fatalf("logout changed route or retained login: %+v %v", status, err) - } - if _, err := restarted.openAI.Credentials(t.Context()); !errors.Is(err, openaiauth.ErrSignInRequired) { - t.Fatalf("credentials survived logout: %v", err) - } -} - -func TestOpenAISetupRetryUsesSavedLogin(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "generation") - service.refreshModels = func(context.Context, string, config.Provider) error { return nil } - t.Cleanup(service.Close) - if err := service.openAI.Install(t.Context(), service.openAI.Generation(), openAITestCredentials()); err != nil { - t.Fatal(err) - } - service.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { - t.Error("requested new OAuth authorization for an already saved login") - return openaiauth.Credentials{}, errors.New("unexpected login") - } - status, err := service.ProviderStatus(openaiauth.Provider) - if err != nil || status.AuthState != "setup_required" { - t.Fatalf("partial setup was reported ready: %+v %v", status, err) - } - flow, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - waitProviderState(t, service, flow.FlowID, "succeeded") -} - -func TestOpenAILogoutCancelsOnlyOwnFlows(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "generation") - t.Cleanup(service.Close) - service.openAILogin = func(ctx context.Context, _ func(string, string)) (openaiauth.Credentials, error) { - <-ctx.Done() - return openaiauth.Credentials{}, ctx.Err() - } - service.login = func(ctx context.Context, _ func(string, string)) (providerLoginIdentity, error) { - <-ctx.Done() - return providerLoginIdentity{teams: []inferencenet.Team{}}, ctx.Err() - } - openAI, err := service.BeginProviderLogin(openaiauth.Provider) - if err != nil { - t.Fatal(err) - } - inference, err := service.BeginLogin() - if err != nil { - t.Fatal(err) - } - if _, err := service.LogoutProvider(t.Context(), openaiauth.Provider); err != nil { - t.Fatal(err) - } - waitProviderState(t, service, openAI.FlowID, "interrupted") - status, err := service.LoginStatus(inference.FlowID) - if err != nil || status.State != "authorizing" { - t.Fatalf("cancelled unrelated provider: %v", err) - } -} - -func TestOpenAIRejectsConflictingProfileBeforeLogin(t *testing.T) { - directory := t.TempDir() - t.Setenv("WHIPCODE_HOME", directory) - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.Providers[openaiauth.Provider] = config.Provider{API: "openai-completions", BaseURL: "https://example.com"} - return nil - }) - if err != nil { - t.Fatal(err) - } - before, err := os.ReadFile(filepath.Join(directory, "config.json")) - if err != nil { - t.Fatal(err) - } - service := NewProviderService(t.Context(), "generation") - t.Cleanup(service.Close) - if _, err := service.BeginProviderLogin(openaiauth.Provider); err == nil { - t.Fatal("accepted conflicting route") - } - after, err := os.ReadFile(filepath.Join(directory, "config.json")) - if err != nil || string(before) != string(after) { - t.Fatal("changed existing configuration") - } -} - func TestOpenAILoginAcrossUnixAndWebSocketWithoutJournalingSecrets(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) ready, release := make(chan struct{}), make(chan struct{}) @@ -346,43 +99,3 @@ func TestOpenAILoginAcrossUnixAndWebSocketWithoutJournalingSecrets(t *testing.T) t.Fatal("authentication secrets reached the durable event log") } } - -func TestOpenAICatalogIsScopedToConnectedAccount(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - service := NewProviderService(t.Context(), "catalog") - t.Cleanup(service.Close) - credentials := openAITestCredentials() - if err := service.openAI.Install(t.Context(), service.openAI.Generation(), credentials); err != nil { - t.Fatal(err) - } - cfg := config.Default() - if err := cfg.UpsertOpenAICodex(); err != nil { - t.Fatal(err) - } - cfg.Providers["api"] = config.Provider{BaseURL: "https://example.com", APIKey: "api-fixture-key"} - if err := cfg.Save(); err != nil { - t.Fatal(err) - } - if err := config.SaveCatalogs(map[string]config.Catalog{ - openaiauth.Provider: {BaseURL: openaiauth.BaseURL, AccountID: credentials.AccountID}, - "api": {BaseURL: "https://example.com"}, - }); err != nil { - t.Fatal(err) - } - if len(service.Catalogs()) != 2 { - t.Fatal("connected account's catalog disappeared") - } - credentials.AccountID = "replacement-account" - if err := service.openAI.Install(t.Context(), service.openAI.Generation(), credentials); err != nil { - t.Fatal(err) - } - if catalogs := service.Catalogs(); len(catalogs) != 1 || catalogs["api"].BaseURL == "" { - t.Fatal("replacement account could see the previous subscription catalog") - } - if _, err := service.LogoutProvider(t.Context(), openaiauth.Provider); err != nil { - t.Fatal(err) - } - if _, exists := config.LoadCatalogs()[openaiauth.Provider]; exists { - t.Fatal("logout retained the subscription catalog on disk") - } -} diff --git a/internal/daemon/provider_selection_test.go b/internal/daemon/provider_selection_test.go index 38598fac8..e9d5c8221 100644 --- a/internal/daemon/provider_selection_test.go +++ b/internal/daemon/provider_selection_test.go @@ -1,252 +1,14 @@ package daemon import ( - "context" "encoding/json" - "errors" - "os" - "path/filepath" - "sync" - "sync/atomic" "testing" - "time" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" ) -func TestProviderSelectionPreservesRoutesAndRecommendsOnlyAvailableModels(t *testing.T) { - for _, test := range []struct { - name string - inference, router bool - model, provider string - ready bool - wantProvider string - }{ - {name: "clean", wantProvider: "inference-net"}, - {name: "inference detected", inference: true, ready: true, wantProvider: "inference-net"}, - {name: "router detected leaves default explicit", router: true, wantProvider: "inference-net"}, - {name: "explicit router", inference: true, router: true, model: "moonshotai/kimi-k2.5", provider: "openrouter", ready: true, wantProvider: "openrouter"}, - {name: "unknown explicit model", inference: true, model: "unknown", provider: "inference-net", wantProvider: "inference-net"}, - } { - t.Run(test.name, func(t *testing.T) { - s := providerConnectionsFixture(t) - if test.inference { - t.Setenv(config.InferenceNetEnvVar, "fixture") - } - if test.router { - t.Setenv(config.OpenRouterEnvVar, "fixture") - } - if _, err := config.Load(); err != nil { - t.Fatal(err) - } - if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, FetchedAt: time.Now(), Models: []config.ModelInfoLite{{ID: "alphabetically-first"}, {ID: "moonshotai/kimi-k2.5"}}}); err != nil { - t.Fatal(err) - } - list, err := s.ListProvidersFor(test.model, test.provider) - if err != nil { - t.Fatal(err) - } - if list.Selection == nil || list.Selection.Ready != test.ready || list.Selection.Provider != test.wantProvider { - t.Fatalf("selection = %+v", list.Selection) - } - if list.Providers[0].ID != config.InferenceNetProvider || !list.Providers[0].Recommended { - t.Fatal("missing restrained Inference.net preference") - } - if test.router && providerEntry(t, s, "openrouter").SuggestedModel != "moonshotai/kimi-k2.5" { - t.Fatal("did not recommend an available coding candidate") - } - cfg, err := config.Load() - if err != nil || cfg.DefaultModel != "kimi-k3-fast" || cfg.DefaultProvider != "" { - t.Fatal("inventory changed defaults") - } - }) - } -} - -func TestProviderSelectionMatchesCatalogRoutePrecedence(t *testing.T) { - for _, test := range []struct { - name, explicit string - shared bool - want string - }{ - {name: "catalog route precedes host default", want: "catalog-provider"}, - {name: "host default does not resolve ambiguity", shared: true}, - {name: "explicit route resolves ambiguity", shared: true, explicit: "default-provider", want: "default-provider"}, - } { - t.Run(test.name, func(t *testing.T) { - s := providerConnectionsFixture(t) - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.DefaultProvider = "default-provider" - for _, name := range []string{"default-provider", "catalog-provider"} { - cfg.Providers[name] = config.Provider{BaseURL: "https://" + name + ".test/v1", APIKey: "fixture"} - } - return nil - }) - if err != nil { - t.Fatal(err) - } - for _, name := range []string{"default-provider", "catalog-provider"} { - catalog := config.Catalog{BaseURL: "https://" + name + ".test/v1"} - if name == "catalog-provider" || test.shared { - catalog.Models = []config.ModelInfoLite{{ID: "catalog-only-model"}} - } - if err := config.UpdateCatalog(name, catalog); err != nil { - t.Fatal(err) - } - } - cfg, err := config.Load() - if err != nil { - t.Fatal(err) - } - route, _, _, _, routeErr := cfg.ResolveRoute("catalog-only-model", test.explicit) - list, err := s.ListProvidersFor("catalog-only-model", test.explicit) - if err != nil { - t.Fatal(err) - } - selection := list.Selection - if route != test.want || (routeErr == nil) != (test.want != "") || selection.Ready != (routeErr == nil) || selection.Provider != route { - t.Fatalf("runtime route=%q err=%v, readiness=%+v, want route=%q", route, routeErr, selection, test.want) - } - }) - } -} - -func TestProviderSelectionRespectsDisabledCustomAndCredentialCommands(t *testing.T) { - s := providerConnectionsFixture(t) - marker := filepath.Join(t.TempDir(), "secret-command-executed") - _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.DefaultProvider, cfg.DefaultModel = "custom", "coding" - cfg.Providers["custom"] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "!touch " + marker} - cfg.Models["coding"] = config.Model{Providers: []string{"custom"}} - cfg.DisabledProviders = []string{"inference-net"} - return nil - }) - if err != nil { - t.Fatal(err) - } - list, err := s.ListProviders() - if err != nil || !list.Selection.Ready || list.Selection.Provider != "custom" { - t.Fatalf("selection = %+v, %v", list.Selection, err) - } - if list.Providers[0].Recommended { - t.Fatal("promoted a disabled provider") - } - if _, err := os.Stat(marker); !errors.Is(err, os.ErrNotExist) { - t.Fatal("executed a credential command during discovery") - } - _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { - cfg.DisabledProviders = nil - cfg.Providers["inference-net"] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "fixture"} - return nil - }) - if err != nil { - t.Fatal(err) - } - if providerEntry(t, s, "inference-net").Recommended { - t.Fatal("promoted a custom endpoint as Inference.net") - } -} - -func TestProviderDefaultPairValidationAndPersistence(t *testing.T) { - s := providerConnectionsFixture(t) - t.Setenv(config.OpenRouterEnvVar, "fixture") - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, Models: []config.ModelInfoLite{{ID: "moonshotai/kimi-k2.5", ReasoningEfforts: []string{"low"}}}}); err != nil { - t.Fatal(err) - } - model, provider := "moonshotai/kimi-k2.5", "openrouter" - _, err = s.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DefaultModel: new("not-advertised"), DefaultProvider: &provider}) - if err == nil { - t.Fatal("accepted an unavailable model") - } - updated, err := s.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DefaultModel: &model, DefaultProvider: &provider, DefaultEffort: new("")}) - if err != nil { - t.Fatal(err) - } - if _, err := s.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DefaultModel: &model, DefaultProvider: &provider}); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatalf("stale update = %v", err) - } - restarted := NewProviderService(t.Context(), "restarted") - t.Cleanup(restarted.Close) - list, err := restarted.ListProviders() - if err != nil || !list.Selection.Ready || list.Selection.Model != model || list.Selection.Provider != provider || list.Revision != updated.Revision { - t.Fatalf("restarted selection = %+v, %v", list.Selection, err) - } -} - -func TestProviderLoginSkipsOnlySingletonChoices(t *testing.T) { - s := providerConnectionsFixture(t) - s.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { - return providerLoginIdentity{token: "fixture-secret", teams: []inferencenet.Team{{ID: "team", Name: "Only workspace"}}}, nil - } - s.projects = func(context.Context, string, inferencenet.Team) ([]inferencenet.Project, error) { - return []inferencenet.Project{{ID: "project", Name: "Only project"}}, nil - } - finished := make(chan inferencenet.Auth, 1) - s.finish = func(_ context.Context, auth inferencenet.Auth) error { finished <- auth; return nil } - s.create = func(context.Context, string, inferencenet.Team, string) (inferencenet.Project, error) { - t.Error("automatically created a project") - return inferencenet.Project{}, errors.New("unexpected create") - } - flow, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - status := waitProviderState(t, s, flow.FlowID, "succeeded") - if status.TeamID != "team" || status.ProjectID != "project" { - t.Fatalf("lost selected context: %+v", status) - } - if auth := <-finished; auth.ProjectID != "project" || auth.TeamID != "team" { - t.Fatalf("wrong provisioned context: %+v", auth) - } - if _, err := s.SelectLoginProject(flow.FlowID, "project"); err == nil { - t.Fatal("duplicate provisioning allowed") - } -} - -func TestConcurrentInferenceLoginReusesActiveFlow(t *testing.T) { - s := providerConnectionsFixture(t) - var calls atomic.Int32 - s.login = func(ctx context.Context, _ func(string, string)) (providerLoginIdentity, error) { - calls.Add(1) - <-ctx.Done() - return providerLoginIdentity{}, ctx.Err() - } - var wg sync.WaitGroup - ids := make(chan string, 8) - for range 8 { - wg.Go(func() { - flow, err := s.BeginLogin() - if err != nil { - t.Error(err) - return - } - ids <- flow.FlowID - }) - } - wg.Wait() - close(ids) - var first string - for id := range ids { - if first != "" && id != first { - t.Fatalf("concurrent login created different flows: %q and %q", first, id) - } - first = id - } - if first == "" { - t.Fatal("no login flow returned") - } - s.Close() - if calls.Load() != 1 { - t.Fatalf("started %d login attempts", calls.Load()) - } -} - func TestProviderListRPCSelectionParameters(t *testing.T) { params, err := json.Marshal(protocol.ProviderListParams{Model: "explicit", Provider: "openrouter"}) if err != nil { @@ -285,7 +47,7 @@ func TestProviderCatalogDefaultPairSurvivesSharedModelsAndRestart(t *testing.T) if err != nil { t.Fatalf("could not save an explicit catalog-only default pair: %v", err) } - restarted := NewProviderService(t.Context(), "catalog-default-restarted") + restarted := providersvc.NewProviderService(t.Context(), "catalog-default-restarted") t.Cleanup(restarted.Close) list, err := restarted.ListProviders() if err != nil || list.Revision != updated.Revision || list.Selection == nil || !list.Selection.Ready || list.Selection.Model != model || list.Selection.Provider != provider { diff --git a/internal/daemon/provider_service_test.go b/internal/daemon/provider_service_test.go index 04f825942..f89b11967 100644 --- a/internal/daemon/provider_service_test.go +++ b/internal/daemon/provider_service_test.go @@ -1,274 +1,13 @@ package daemon import ( - "context" - "encoding/json" - "errors" - "strings" "testing" - "time" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/inferencenet" - "github.com/context-labs/whip/internal/llm" + providersvc "github.com/context-labs/whip/internal/provider" ) -func waitProviderState(t *testing.T, service *ProviderService, id, state string) ProviderLoginStatus { - t.Helper() - deadline := time.Now().Add(2 * time.Second) - for time.Now().Before(deadline) { - result, err := service.LoginStatus(id) - if err != nil { - t.Fatal(err) - } - if result.State == state { - return result - } - time.Sleep(time.Millisecond) - } - result, _ := service.LoginStatus(id) - t.Fatalf("wanted %s, got %s", state, result.State) - return ProviderLoginStatus{} -} - -func TestProviderLoginReconnectChoicesAndSecretIsolation(t *testing.T) { - s := NewProviderService(t.Context(), "generation-a") - defer s.Close() - s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { - code("https://example.com/verify", "public-code") - return providerLoginIdentity{token: "secret-session-token", email: "person@example.com", teams: []inferencenet.Team{{ID: "team", Name: "Team"}, {ID: "other", Name: "Other"}}}, nil - } - s.projects = func(ctx context.Context, token string, team inferencenet.Team) ([]inferencenet.Project, error) { - if token != "secret-session-token" || team.ID != "team" { - return nil, errors.New("bad selection") - } - return []inferencenet.Project{{ID: "project", Name: "Project"}, {ID: "other", Name: "Other"}}, nil - } - finished := make(chan inferencenet.Auth, 1) - s.finish = func(ctx context.Context, auth inferencenet.Auth) error { finished <- auth; return nil } - started, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - status := waitProviderState(t, s, started.FlowID, "choose_team") - if status.VerificationURL == "" || len(status.Teams) != 2 { - t.Fatal("missing reconnect choices") - } - status.Teams[0].ID = "mutated" - if _, err := s.SelectLoginTeam(started.FlowID, "invalid"); err == nil { - t.Fatal("accepted unknown team") - } - if _, err := s.SelectLoginTeam(started.FlowID, "team"); err != nil { - t.Fatal(err) - } - waitProviderState(t, s, started.FlowID, "choose_project") - if _, err := s.SelectLoginProject(started.FlowID, "project"); err != nil { - t.Fatal(err) - } - status = waitProviderState(t, s, started.FlowID, "succeeded") - auth := <-finished - if auth.SessionToken != "secret-session-token" || auth.ProjectID != "project" || auth.TeamName != "Team" { - t.Fatal("missing host-side auth") - } - encoded, err := json.Marshal(status) - if err != nil { - t.Fatal(err) - } - if strings.Contains(string(encoded), "secret") || strings.Contains(string(encoded), "SessionToken") { - t.Fatal("secret exposed") - } - s.mu.Lock() - retained := s.flows[started.FlowID].token - s.mu.Unlock() - if retained != "" { - t.Fatal("flow retained session token after completion") - } - if _, err := s.SelectLoginProject(started.FlowID, "project"); err == nil { - t.Fatal("duplicate provisioning admitted") - } -} - -func TestProviderLoginCancellationExpiryAndRestart(t *testing.T) { - for _, action := range []string{"cancel", "expire", "restart"} { - t.Run(action, func(t *testing.T) { - s := NewProviderService(t.Context(), "generation-a") - s.lifetime = 20 * time.Millisecond - s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { - <-ctx.Done() - return providerLoginIdentity{}, ctx.Err() - } - started, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - switch action { - case "cancel": - if _, err := s.CancelLogin(started.FlowID); err != nil { - t.Fatal(err) - } - waitProviderState(t, s, started.FlowID, "cancelled") - case "expire": - waitProviderState(t, s, started.FlowID, "expired") - case "restart": - s.Close() - next := NewProviderService(t.Context(), "generation-b") - defer next.Close() - status, err := next.LoginStatus(started.FlowID) - if err != nil || status.State != "interrupted" { - t.Fatalf("restart: %+v %v", status, err) - } - } - s.Close() - }) - } -} - -func TestProviderSetupRevisionAndSafeConfiguration(t *testing.T) { - t.Setenv("WHIPCODE_HOME", t.TempDir()) - s := NewProviderService(t.Context(), "generation") - defer s.Close() - s.validate = func(ctx context.Context, url, key string) ([]llm.ModelInfo, error) { - if key != "secret-key" { - return nil, errors.New("invalid key") - } - return []llm.ModelInfo{{ID: "fixture-chat-model"}}, nil - } - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - after, err := s.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "secret-key"}) - if err != nil { - t.Fatal(err) - } - if after.Revision == before.Revision { - t.Fatal("revision did not change") - } - if _, err := s.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "secret-key"}); !errors.Is(err, config.ErrRevisionConflict) { - t.Fatalf("conflict: %v", err) - } - c, err := config.Load() - if err != nil { - t.Fatal(err) - } - if c.Providers["openrouter"].APIKey != "secret-key" { - t.Fatal("key not saved on host") - } - encoded, _ := json.Marshal(after) - if strings.Contains(string(encoded), "secret-key") { - t.Fatal("configuration exposed credential") - } -} - -func TestProviderLoginListRecoversLostAcknowledgementAndIsBounded(t *testing.T) { - s := NewProviderService(t.Context(), "generation") - defer s.Close() - s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { - <-ctx.Done() - return providerLoginIdentity{}, ctx.Err() - } - var first string - for range 64 { - flow, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - if first == "" { - first = flow.FlowID - recovered, err := s.BeginLogin() - if err != nil || recovered.FlowID != first || len(s.ListLogins().Flows) != 1 { - t.Fatal("lost begin acknowledgement did not recover the existing flow") - } - } - if _, err := s.CancelLogin(flow.FlowID); err != nil { - t.Fatal(err) - } - } - if _, err := s.BeginLogin(); err == nil { - t.Fatal("retained login bound was not enforced") - } - result := s.ListLogins() - if len(result.Flows) != 64 { - t.Fatal("retained login outcomes were lost") - } - s.mu.Lock() - s.flows[first].status.ExpiresAt = time.Now().Add(-time.Second) - s.mu.Unlock() - if _, err := s.BeginLogin(); err != nil { - t.Fatal("expired terminal login did not release capacity") - } -} - -func TestProviderFailureDoesNotExposeUpstreamSecret(t *testing.T) { - s := NewProviderService(t.Context(), "generation") - defer s.Close() - s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { - return providerLoginIdentity{}, errors.New("upstream echoed secret-token") - } - result, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - result = waitProviderState(t, s, result.FlowID, "failed") - encoded, _ := json.Marshal(result) - if strings.Contains(string(encoded), "secret-token") { - t.Fatal("upstream secret exposed to client") - } -} - -func TestProviderLoginChangesWorkspaceBeforeProvisioning(t *testing.T) { - s := NewProviderService(t.Context(), "workspace-change") - defer s.Close() - s.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { - return providerLoginIdentity{token: "test-token", teams: []inferencenet.Team{{ID: "a"}, {ID: "b"}}}, nil - } - release := make(chan struct{}) - s.projects = func(ctx context.Context, _ string, team inferencenet.Team) ([]inferencenet.Project, error) { - if team.ID == "b" { - select { - case <-release: - case <-ctx.Done(): - return nil, ctx.Err() - } - } - return []inferencenet.Project{{ID: team.ID + "-1"}, {ID: team.ID + "-2"}}, nil - } - started, err := s.BeginLogin() - if err != nil { - t.Fatal(err) - } - waitProviderState(t, s, started.FlowID, "choose_team") - if _, err := s.SelectLoginTeam(started.FlowID, "a"); err != nil { - t.Fatal(err) - } - waitProviderState(t, s, started.FlowID, "choose_project") - loading, err := s.SelectLoginTeam(started.FlowID, "b") - if err != nil { - t.Fatal(err) - } - if loading.State != "loading_projects" || loading.TeamID != "b" || len(loading.Projects) != 0 { - t.Fatalf("retained previous workspace: %+v", loading) - } - if _, err := s.SelectLoginTeam(started.FlowID, "a"); err == nil { - t.Fatal("allowed overlapping project discovery") - } - close(release) - ready := waitProviderState(t, s, started.FlowID, "choose_project") - if len(ready.Projects) != 2 || ready.Projects[0].ID != "b-1" { - t.Fatalf("wrong workspace projects: %+v", ready.Projects) - } - if _, err := s.SelectLoginProject(started.FlowID, "a-1"); err == nil { - t.Fatal("accepted previous workspace project") - } - if _, err := s.CancelLogin(started.FlowID); err != nil { - t.Fatal(err) - } - if _, err := s.SelectLoginTeam(started.FlowID, "a"); err == nil { - t.Fatal("resumed a cancelled login") - } -} - -func compactionConfigurationFixture(t *testing.T) (*ProviderService, *config.Config) { +func compactionConfigurationFixture(t *testing.T) (*providersvc.ProviderService, *config.Config) { t.Helper() t.Setenv("WHIPCODE_HOME", t.TempDir()) t.Setenv("WHIP_TEST_MISSING_COMPACTION_KEY", "") @@ -299,142 +38,7 @@ func compactionConfigurationFixture(t *testing.T) (*ProviderService, *config.Con }); err != nil { t.Fatal(err) } - s := NewProviderService(t.Context(), "compaction-settings") + s := providersvc.NewProviderService(t.Context(), "compaction-settings") t.Cleanup(s.Close) return s, cfg } - -func TestProviderCompactionConfigurationSelections(t *testing.T) { - tests := []struct { - name string - model string - provider string - wantProvider string - wantErr bool - }{ - {name: "alias resolves provider", model: "summary", wantProvider: "ready"}, - {name: "catalog resolves provider", model: "catalog-only", wantProvider: "ready"}, - {name: "explicit route", model: "summary", provider: "ready", wantProvider: "ready"}, - {name: "automatic clears provider", provider: "stale"}, - {name: "unknown model", model: "missing", provider: "ready", wantErr: true}, - {name: "unknown provider", model: "summary", provider: "missing", wantErr: true}, - {name: "missing credentials", model: "offline-summary", wantErr: true}, - {name: "disabled provider", model: "disabled-summary", wantErr: true}, - {name: "wrong provider", model: "summary", provider: "other", wantErr: true}, - {name: "ambiguous route", model: "ambiguous", wantErr: true}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - s, _ := compactionConfigurationFixture(t) - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - after, err := s.UpdateConfiguration(ConfigurationUpdate{ - Revision: before.Revision, CompactModel: &test.model, CompactProvider: &test.provider, - CompactPercent: new(60), MaxRetries: new(3), - }) - if (err != nil) != test.wantErr { - t.Fatalf("update error = %v, wantErr %t", err, test.wantErr) - } - persisted, readErr := s.ReadConfiguration() - if readErr != nil { - t.Fatal(readErr) - } - if test.wantErr { - if persisted.Revision != before.Revision { - t.Fatal("invalid route partially saved configuration") - } - return - } - if after.CompactModel != test.model || after.CompactProvider != test.wantProvider { - t.Fatalf("compaction selection = %q %q; want %q %q", - after.CompactModel, after.CompactProvider, test.model, test.wantProvider) - } - if persisted.CompactModel != after.CompactModel || persisted.CompactProvider != after.CompactProvider { - t.Fatal("resolved model and provider were not persisted together") - } - if after.CompactPercent != 60 || after.MaxRetries != 3 { - t.Fatal("valid settings were not saved atomically") - } - }) - } -} - -func TestProviderCompactionConfigurationPreservesUnchangedLegacyOverrides(t *testing.T) { - for _, model := range []string{"deepseek-v4-flash-0731", "missing-summary"} { - t.Run(model, func(t *testing.T) { - s, cfg := compactionConfigurationFixture(t) - cfg.CompactModel, cfg.CompactProvider, cfg.CompactPct = model, "missing-provider", 95 - if err := cfg.Save(); err != nil { - t.Fatal(err) - } - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - after, err := s.UpdateConfiguration(ConfigurationUpdate{ - Revision: before.Revision, CompactModel: &before.CompactModel, - CompactProvider: &before.CompactProvider, CompactPercent: &before.CompactPercent, - DefaultModel: &before.DefaultModel, DefaultProvider: &before.DefaultProvider, MaxRetries: new(4), - }) - if err != nil { - t.Fatal(err) - } - if after.CompactModel != model || after.CompactProvider != "missing-provider" || after.CompactPercent != 95 || after.MaxRetries != 4 { - t.Fatalf("legacy override was changed: %+v", after) - } - if _, err := s.UpdateConfiguration(ConfigurationUpdate{ - Revision: after.Revision, CompactProvider: new("different-missing-provider"), - }); err == nil { - t.Fatal("changed legacy route was not validated") - } - cleared, err := s.UpdateConfiguration(ConfigurationUpdate{ - Revision: after.Revision, CompactModel: new(""), CompactProvider: &after.CompactProvider, - }) - if err != nil || cleared.CompactModel != "" || cleared.CompactProvider != "" { - t.Fatalf("automatic did not clear override: %+v %v", cleared, err) - } - }) - } -} - -func TestProviderCompactionConfigurationThresholdValidation(t *testing.T) { - for _, test := range []struct { - name string - percent int - wantErr bool - }{ - {name: "automatic"}, - {name: "minimum", percent: 10}, - {name: "maximum", percent: 90}, - {name: "negative", percent: -1, wantErr: true}, - {name: "below minimum", percent: 9, wantErr: true}, - {name: "above maximum", percent: 91, wantErr: true}, - {name: "over 100", percent: 101, wantErr: true}, - } { - t.Run(test.name, func(t *testing.T) { - s, _ := compactionConfigurationFixture(t) - before, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - after, err := s.UpdateConfiguration(ConfigurationUpdate{ - Revision: before.Revision, CompactPercent: &test.percent, MaxRetries: new(5), - }) - if (err != nil) != test.wantErr { - t.Fatalf("threshold error = %v, wantErr %t", err, test.wantErr) - } - if !test.wantErr && after.CompactPercent != test.percent { - t.Fatalf("threshold = %d, want %d", after.CompactPercent, test.percent) - } - persisted, err := s.ReadConfiguration() - if err != nil { - t.Fatal(err) - } - if test.wantErr && persisted.Revision != before.Revision { - t.Fatal("invalid threshold partially saved configuration") - } - }) - } -} diff --git a/internal/daemon/query.go b/internal/daemon/query.go index e332af433..9d901e14e 100644 --- a/internal/daemon/query.go +++ b/internal/daemon/query.go @@ -8,6 +8,7 @@ import ( "github.com/context-labs/whip/internal/browser" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" ) @@ -115,7 +116,7 @@ func (c *Client) Query(ctx context.Context, params protocol.QueryParams) (protoc return result, err } -func queryProviderCatalogs(ctx context.Context, providers *ProviderService, payload json.RawMessage) (string, error) { +func queryProviderCatalogs(ctx context.Context, providers *providersvc.ProviderService, payload json.RawMessage) (string, error) { var params protocol.ProviderCatalogParams if len(payload) > 0 { if err := json.Unmarshal(payload, ¶ms); err != nil { diff --git a/internal/daemon/server.go b/internal/daemon/server.go index 8c3df44bd..3239222e8 100644 --- a/internal/daemon/server.go +++ b/internal/daemon/server.go @@ -20,6 +20,7 @@ import ( "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" ) @@ -46,7 +47,7 @@ type ServerOptions struct { } type Server struct { - providers *ProviderService + providers *providersvc.ProviderService hostMCP *hostMCPService daemon *Daemon options ServerOptions @@ -126,7 +127,7 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { } providers := value.providers if providers == nil { - providers = NewProviderService(ctx, strconv.FormatInt(options.Generation, 10)) + providers = providersvc.NewProviderService(ctx, strconv.FormatInt(options.Generation, 10)) } server := &Server{ daemon: value, options: options, ctx: ctx, cancel: cancel, runtimeID: runtimeID, providers: providers, diff --git a/internal/daemon/session.go b/internal/daemon/session.go index d125ee823..c9c25dc9f 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -19,6 +19,7 @@ import ( "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" sessionstore "github.com/context-labs/whip/internal/session" ) @@ -283,7 +284,7 @@ func (s *supervisor) wait() { type Session struct { titleChanged func(string) - providers *ProviderService + providers *providersvc.ProviderService store *sessionstore.Store // Identity is fixed for the root's lifetime. Saved facts (title, goal, // archive state, directory) are read from the store when a decision needs diff --git a/internal/daemon/subscription_runtime_test.go b/internal/daemon/subscription_runtime_test.go index d78514472..a8fea9544 100644 --- a/internal/daemon/subscription_runtime_test.go +++ b/internal/daemon/subscription_runtime_test.go @@ -15,6 +15,7 @@ import ( "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/openaiauth" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" @@ -38,7 +39,7 @@ func TestSubscriptionRecursiveRuntimeToolsHelpersTitleAndCompaction(t *testing.T t.Fatal(err) } credentials.Close() - providers := NewProviderService(t.Context(), "subscription-runtime") + providers := providersvc.NewProviderService(t.Context(), "subscription-runtime") t.Cleanup(providers.Close) if _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { return cfg.UpsertOpenAICodex() }); err != nil { t.Fatal(err) diff --git a/internal/daemon/default_permission_configuration_test.go b/internal/provider/default_permission_configuration_test.go similarity index 83% rename from internal/daemon/default_permission_configuration_test.go rename to internal/provider/default_permission_configuration_test.go index d92c99331..e2fcf6ee9 100644 --- a/internal/daemon/default_permission_configuration_test.go +++ b/internal/provider/default_permission_configuration_test.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "bytes" @@ -9,6 +9,7 @@ import ( "testing" "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/protocol" ) func TestConfigurationDefaultPermissionMode(t *testing.T) { @@ -36,14 +37,14 @@ func TestConfigurationDefaultPermissionMode(t *testing.T) { t.Fatalf("resolved default omitted: %s", encoded) } for _, mode := range []string{"automatic", "prompt"} { - after, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DefaultPermissionMode: &mode}) + after, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DefaultPermissionMode: &mode}) if err != nil { t.Fatal(err) } if after.DefaultPermissionMode != mode || after.Revision == before.Revision { t.Fatalf("update = %+v", after) } - if _, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DefaultPermissionMode: &mode}); !errors.Is(err, config.ErrRevisionConflict) { + if _, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DefaultPermissionMode: &mode}); !errors.Is(err, config.ErrRevisionConflict) { t.Fatalf("stale update = %v", err) } persisted, _, err := config.ReadVersioned() @@ -67,7 +68,7 @@ func TestConfigurationDefaultPermissionMode(t *testing.T) { t.Fatal(err) } brandIcons := !before.BrandIcons - _, err = service.UpdateConfiguration(ConfigurationUpdate{ + _, err = service.UpdateConfiguration(protocol.ConfigurationUpdate{ Revision: before.Revision, DefaultPermissionMode: &mode, BrandIcons: &brandIcons, }) if err == nil { diff --git a/internal/provider/main_test.go b/internal/provider/main_test.go new file mode 100644 index 000000000..1ad9bd597 --- /dev/null +++ b/internal/provider/main_test.go @@ -0,0 +1,106 @@ +package provider + +import ( + "errors" + "fmt" + "net/http" + "os" + "os/exec" + "path/filepath" + "sync/atomic" + "testing" + + "github.com/context-labs/whip/internal/config" +) + +// Model requests and discovery in tests must not depend on, or expose, the +// developer's credentials, standing instructions or installed skills. Tests may +// override these fixtures. +func TestMain(m *testing.M) { + home, err := os.MkdirTemp("", "whip-provider-test-home-") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + if err = os.Setenv("HOME", home); err == nil { + err = os.Setenv("WHIPCODE_HOME", filepath.Join(home, ".whipcode")) + } + if err == nil { + err = os.Unsetenv("XDG_CONFIG_HOME") // OpenCode discovery would read it before HOME + } + if err == nil { + for _, name := range providerTestEnvironment() { + if err = os.Unsetenv(name); err != nil { + break + } + } + } + if err != nil { + os.RemoveAll(home) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + code := m.Run() + os.RemoveAll(home) + os.Exit(code) +} + +func providerTestEnvironment() []string { + names := []string{"OPENAI_BASE_URL", "OPENAI_API_BASE"} + for _, preset := range config.ProviderPresets() { + names = append(names, preset.EnvironmentVariables...) + } + return names +} + +func TestProviderTestEnvironment(t *testing.T) { + const child = "WHIP_TEST_PROVIDER_ENV_CHILD" + if os.Getenv(child) == "" { + command := exec.CommandContext(t.Context(), os.Args[0], "-test.run=^TestProviderTestEnvironment$") + command.Env = append(os.Environ(), child+"=1") + for _, name := range providerTestEnvironment() { + command.Env = append(command.Env, name+"=inherited-provider-fixture") + } + if output, err := command.CombinedOutput(); err != nil { + t.Fatalf("inherited provider environment was not isolated: %v\n%s", err, output) + } + return + } + + // Exercise TestMain in a fresh process with harmless inherited keys. Trap + // every HTTP request so a regression cannot reach a real provider. + var requests atomic.Int64 + previous := http.DefaultTransport + http.DefaultTransport = catalogTransport(func(*http.Request) (*http.Response, error) { + requests.Add(1) + return nil, errors.New("unexpected provider request in isolated tests") + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + for _, name := range providerTestEnvironment() { + if _, exists := os.LookupEnv(name); exists { + t.Errorf("inherited %s survived TestMain", name) + } + } + cfg := &config.Config{Providers: map[string]config.Provider{}} + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + if got := cfg.EffectiveProviders(); len(got) != 0 { + t.Errorf("empty fixture discovered %d inherited providers", len(got)) + } + service := NewProviderService(t.Context(), "isolated-test-environment") + t.Cleanup(service.Close) + if _, err := service.ListCatalogs(t.Context(), false, ""); err != nil { + t.Fatal(err) + } + if got := requests.Load(); got != 0 { + t.Errorf("empty fixture made %d provider requests", got) + } + + // Tests can still opt into discovery explicitly after suite isolation. + t.Setenv(config.OpenRouterEnvVar, "explicit-provider-fixture") + providers := cfg.EffectiveProviders() + if provider, ok := providers["openrouter"]; !ok || len(providers) != 1 || !provider.KeyStatus(cfg).Available { + t.Fatal("explicit test key did not discover exactly its provider") + } +} diff --git a/internal/daemon/provider_account.go b/internal/provider/provider_account.go similarity index 59% rename from internal/daemon/provider_account.go rename to internal/provider/provider_account.go index 50f9cb492..ceeb41df0 100644 --- a/internal/daemon/provider_account.go +++ b/internal/provider/provider_account.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "cmp" @@ -13,47 +13,41 @@ import ( "github.com/context-labs/whip/internal/protocol" ) -type ( - ProviderLoginList = protocol.ProviderLoginList - ProviderNameParams = protocol.ProviderNameParams - ProviderStatus = protocol.ProviderStatus -) - // ListLogins recovers flow identities after a lost begin acknowledgement. // The same bounded retained flow set backs status queries. -func (s *ProviderService) ListLogins() ProviderLoginList { +func (s *ProviderService) ListLogins() protocol.ProviderLoginList { s.mu.Lock() defer s.mu.Unlock() - result := ProviderLoginList{Flows: []ProviderLoginStatus{}} + result := protocol.ProviderLoginList{Flows: []protocol.ProviderLoginStatus{}} for _, flow := range s.flows { result.Flows = append(result.Flows, loginSnapshot(flow)) } - slices.SortFunc(result.Flows, func(a, b ProviderLoginStatus) int { return cmp.Compare(a.FlowID, b.FlowID) }) + slices.SortFunc(result.Flows, func(a, b protocol.ProviderLoginStatus) int { return cmp.Compare(a.FlowID, b.FlowID) }) return result } -func (s *ProviderService) ProviderStatus(provider string) (ProviderStatus, error) { +func (s *ProviderService) ProviderStatus(provider string) (protocol.ProviderStatus, error) { cfg, err := config.Load() if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } return s.providerStatus(cfg, provider) } -func readProviderStatus(provider string) (ProviderStatus, error) { +func readProviderStatus(provider string) (protocol.ProviderStatus, error) { cfg, err := config.Load() if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } return providerKeyStatus(cfg, provider) } -func (s *ProviderService) LogoutProvider(ctx context.Context, provider string) (ProviderStatus, error) { +func (s *ProviderService) LogoutProvider(ctx context.Context, provider string) (protocol.ProviderStatus, error) { if provider == openaiauth.Provider { return s.logoutOpenAI(ctx) } if provider != config.InferenceNetProvider { - return ProviderStatus{}, errors.New("provider does not support account logout") + return protocol.ProviderStatus{}, errors.New("provider does not support account logout") } s.mu.Lock() for _, flow := range s.flows { @@ -69,12 +63,12 @@ func (s *ProviderService) LogoutProvider(ctx context.Context, provider string) ( return s.logoutInferenceNetLocked(ctx) } -func (s *ProviderService) logoutInferenceNetLocked(ctx context.Context) (ProviderStatus, error) { +func (s *ProviderService) logoutInferenceNetLocked(ctx context.Context) (protocol.ProviderStatus, error) { ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() auth, err := inferencenet.LoadAuth() if err != nil { - return ProviderStatus{}, errors.New("could not read provider account on execution host") + return protocol.ProviderStatus{}, errors.New("could not read provider account on execution host") } warnings := []string{} if auth.HasMachineKey() { @@ -88,19 +82,19 @@ func (s *ProviderService) logoutInferenceNetLocked(ctx context.Context) (Provide } } if err := inferencenet.ClearAuth(); err != nil { - return ProviderStatus{}, errors.New("could not remove provider account on execution host") + return protocol.ProviderStatus{}, errors.New("could not remove provider account on execution host") } if err := config.DeleteCatalog(config.InferenceNetProvider); err != nil { - return ProviderStatus{}, errors.New("signed out, but the provider model cache could not be removed") + return protocol.ProviderStatus{}, errors.New("signed out, but the provider model cache could not be removed") } result, err := readProviderStatus(config.InferenceNetProvider) result.Warnings = warnings return result, err } -func (s *ProviderService) RotateProviderKey(ctx context.Context, provider string) (ProviderStatus, error) { +func (s *ProviderService) RotateProviderKey(ctx context.Context, provider string) (protocol.ProviderStatus, error) { if provider != config.InferenceNetProvider { - return ProviderStatus{}, errors.New("provider does not support machine key rotation") + return protocol.ProviderStatus{}, errors.New("provider does not support machine key rotation") } s.provisionMu.Lock() defer s.provisionMu.Unlock() @@ -108,19 +102,19 @@ func (s *ProviderService) RotateProviderKey(ctx context.Context, provider string defer cancel() auth, err := inferencenet.LoadAuth() if err != nil { - return ProviderStatus{}, errors.New("could not read provider account on execution host") + return protocol.ProviderStatus{}, errors.New("could not read provider account on execution host") } if !auth.SignedIn() { - return ProviderStatus{}, errors.New("run provider login before rotating the machine key") + return protocol.ProviderStatus{}, errors.New("run provider login before rotating the machine key") } if _, err := auth.Rotate(ctx); err != nil { - return ProviderStatus{}, errors.New("provider key rotation interrupted; inspect account status before retrying") + return protocol.ProviderStatus{}, errors.New("provider key rotation interrupted; inspect account status before retrying") } if err := inferencenet.SaveAuth(auth); err != nil { - return ProviderStatus{}, errors.New("could not save rotated provider key on execution host") + return protocol.ProviderStatus{}, errors.New("could not save rotated provider key on execution host") } if err := config.DeleteCatalog(provider); err != nil { - return ProviderStatus{}, errors.New("key rotated, but the provider model cache could not be removed") + return protocol.ProviderStatus{}, errors.New("key rotated, but the provider model cache could not be removed") } return readProviderStatus(provider) } diff --git a/internal/provider/provider_behavior_test.go b/internal/provider/provider_behavior_test.go new file mode 100644 index 000000000..63295d96c --- /dev/null +++ b/internal/provider/provider_behavior_test.go @@ -0,0 +1,207 @@ +package provider + +import ( + "context" + "encoding/json" + "errors" + "reflect" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" +) + +func TestProviderConfigurationRejectsInvalidChangesAtomically(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "validation") + defer service.Close() + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + for _, tc := range []struct { + name string + change protocol.ConfigurationUpdate + }{ + {"missing revision", protocol.ConfigurationUpdate{}}, + {"effort", protocol.ConfigurationUpdate{Revision: before.Revision, DefaultEffort: new("turbo")}}, + {"negative compact", protocol.ConfigurationUpdate{Revision: before.Revision, CompactPercent: new(-1)}}, + {"large compact", protocol.ConfigurationUpdate{Revision: before.Revision, CompactPercent: new(101)}}, + {"rounds", protocol.ConfigurationUpdate{Revision: before.Revision, GoalMaxRounds: new(-1)}}, + {"retries", protocol.ConfigurationUpdate{Revision: before.Revision, MaxRetries: new(-1)}}, + } { + t.Run(tc.name, func(t *testing.T) { + if _, err := service.UpdateConfiguration(tc.change); err == nil { + t.Fatal("invalid update accepted") + } + after, err := service.ReadConfiguration() + if err != nil || !reflect.DeepEqual(after, before) { + t.Fatalf("failed update changed configuration: %+v %v", after, err) + } + }) + } + for _, p := range []protocol.ProviderKeySetup{{}, {Revision: before.Revision, Provider: "unknown"}, {Revision: before.Revision, Provider: "openrouter"}} { + if _, err := service.SetProviderKey(t.Context(), p); err == nil { + t.Fatal("invalid key setup accepted") + } + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, errors.New("provider leaked secret-key") + } + if _, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "key"}); err == nil || strings.Contains(err.Error(), "secret-key") { + t.Fatalf("unsafe validation failure: %v", err) + } + if _, err := service.LoginStatus(""); err == nil { + t.Fatal("empty login identity accepted") + } + if _, err := service.CancelLogin("missing"); err == nil { + t.Fatal("missing login cancelled") + } + if _, err := service.SelectLoginTeam("missing", "team"); err == nil { + t.Fatal("missing login selected team") + } + if _, err := service.SelectLoginProject("missing", "project"); err == nil { + t.Fatal("missing login selected project") + } + if _, err := service.CreateLoginProject("missing", ""); err == nil { + t.Fatal("blank project name accepted") + } + service.Close() + if _, err := service.BeginLogin(); !errors.Is(err, context.Canceled) { + t.Fatalf("closed login service: %v", err) + } +} + +func TestProviderLoginFailuresAndCancellationNeverReportSuccess(t *testing.T) { + for _, stage := range []string{"projects", "create", "finish", "cancel_provisioning", "cancel_projects"} { + t.Run(stage, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "failure") + defer service.Close() + entered := make(chan struct{}) + service.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { + return providerLoginIdentity{token: "private-token", teams: []inferencenet.Team{{ID: "team"}, {ID: "other"}}}, nil + } + service.projects = func(ctx context.Context, _ string, _ inferencenet.Team) ([]inferencenet.Project, error) { + if stage == "projects" { + return nil, errors.New("upstream leaked private-token") + } + if stage == "cancel_projects" { + close(entered) + <-ctx.Done() + return nil, ctx.Err() + } + return []inferencenet.Project{{ID: "project"}, {ID: "other"}}, nil + } + service.create = func(context.Context, string, inferencenet.Team, string) (inferencenet.Project, error) { + return inferencenet.Project{}, errors.New("upstream leaked private-token") + } + service.finish = func(ctx context.Context, _ inferencenet.Auth) error { + if stage == "cancel_provisioning" { + close(entered) + <-ctx.Done() + return ctx.Err() + } + return errors.New("upstream leaked private-token") + } + flow, err := service.BeginLogin() + if err != nil { + t.Fatal(err) + } + waitProviderState(t, service, flow.FlowID, "choose_team") + if _, err := service.SelectLoginTeam(flow.FlowID, "team"); err != nil { + t.Fatal(err) + } + if stage != "projects" && stage != "cancel_projects" { + waitProviderState(t, service, flow.FlowID, "choose_project") + if stage == "create" { + _, err = service.CreateLoginProject(flow.FlowID, "created") + } else { + _, err = service.SelectLoginProject(flow.FlowID, "project") + } + if err != nil { + t.Fatal(err) + } + } + want := "failed" + if strings.HasPrefix(stage, "cancel_") { + select { + case <-entered: + case <-time.After(2 * time.Second): + t.Fatal("provider operation did not begin") + } + if _, err := service.CancelLogin(flow.FlowID); err != nil { + t.Fatal(err) + } + want = "cancelled" + if stage == "cancel_provisioning" { + want = "interrupted" + } + } + status := waitProviderState(t, service, flow.FlowID, want) + service.Close() + final, err := service.LoginStatus(flow.FlowID) + if err != nil || final.State != want || final.ProjectID != "" { + t.Fatalf("late completion changed terminal status: %+v %v", final, err) + } + encoded, err := json.Marshal(status) + if err != nil || strings.Contains(string(encoded), "private-token") { + t.Fatalf("secret escaped terminal state: %s %v", encoded, err) + } + if _, err := service.SelectLoginProject(flow.FlowID, "project"); err == nil { + t.Fatal("terminal login allowed another provisioning attempt") + } + }) + } +} + +func TestProviderCompletionPersistsCredentialsOnlyBeforeCancellation(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "persist") + defer service.Close() + auth := inferencenet.Auth{UserEmail: "owner@example.test", TeamName: "Test workspace", ProjectID: "project", ProjectName: "Project", MachineKey: "machine-secret", MachineKeyName: "Host"} + ctx, cancel := context.WithCancel(t.Context()) + cancel() + if err := service.finish(ctx, auth); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled completion=%v", err) + } + before, err := inferencenet.LoadAuth() + if err != nil || before.MachineKey != "" { + t.Fatalf("cancelled completion persisted credentials: %+v %v", before, err) + } + if err := service.finish(t.Context(), inferencenet.Auth{}); err == nil { + t.Fatal("completion without project credentials accepted") + } + if err := service.finish(t.Context(), auth); err != nil { + t.Fatal(err) + } + loaded, err := inferencenet.LoadAuth() + if err != nil || loaded.MachineKey != auth.MachineKey || loaded.ProjectID != auth.ProjectID || loaded.TeamName != auth.TeamName { + t.Fatalf("completion did not persist host credentials: %v", err) + } + status, err := service.ProviderStatus(config.InferenceNetProvider) + if err != nil || !status.Configured || status.Email != auth.UserEmail || status.TeamName != auth.TeamName || status.KeySource != "machine" || status.MachineKeyName != "Host" { + t.Fatalf("safe account identity=%+v %v", status, err) + } + beforeConfig, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + validationCtx, stopValidation := context.WithCancel(t.Context()) + defer stopValidation() + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + stopValidation() + return []llm.ModelInfo{{ID: "valid"}}, nil + } + if _, err := service.SetProviderKey(validationCtx, protocol.ProviderKeySetup{Revision: beforeConfig.Revision, Provider: "openrouter", Key: "replacement-secret"}); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled key setup=%v", err) + } + afterConfig, err := service.ReadConfiguration() + if err != nil || !reflect.DeepEqual(afterConfig, beforeConfig) { + t.Fatalf("cancelled key setup changed config: %+v %v", afterConfig, err) + } +} diff --git a/internal/daemon/provider_catalog.go b/internal/provider/provider_catalog.go similarity index 99% rename from internal/daemon/provider_catalog.go rename to internal/provider/provider_catalog.go index afb645e98..9e3727dd8 100644 --- a/internal/daemon/provider_catalog.go +++ b/internal/provider/provider_catalog.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" diff --git a/internal/daemon/provider_configuration.go b/internal/provider/provider_configuration.go similarity index 99% rename from internal/daemon/provider_configuration.go rename to internal/provider/provider_configuration.go index d5f1d4b7f..9a0f49e11 100644 --- a/internal/daemon/provider_configuration.go +++ b/internal/provider/provider_configuration.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "cmp" diff --git a/internal/provider/provider_configuration_test.go b/internal/provider/provider_configuration_test.go new file mode 100644 index 000000000..f33a7cec0 --- /dev/null +++ b/internal/provider/provider_configuration_test.go @@ -0,0 +1,495 @@ +package provider + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/openaiauth" + "github.com/context-labs/whip/internal/protocol" +) + +func customProviderService(t *testing.T) *ProviderService { + t.Helper() + t.Setenv("WHIPCODE_HOME", t.TempDir()) + s := NewProviderService(t.Context(), "provider-configuration") + t.Cleanup(s.Close) + return s +} + +func customProviderParams(t *testing.T, s *ProviderService) protocol.ProviderCreateParams { + t.Helper() + cfg, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + return protocol.ProviderCreateParams{ + Revision: cfg.Revision, Provider: "custom-test", + Definition: protocol.ProviderDefinition{Name: "My endpoint", BaseURL: "https://example.test/v1", API: "openai-completions"}, + Credential: protocol.ProviderCredential{Mode: "api_key", Key: "private-fixture-key"}, + } +} + +func TestProviderConfigurationCreatePersistAndNoAuthRequests(t *testing.T) { + s := customProviderService(t) + requests := 0 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests++ + if r.Header.Get("Authorization") != "" { + t.Error("unauthenticated discovery sent an Authorization header") + } + if r.URL.Path != "/v1/models" { + t.Errorf("unexpected request %s", r.URL.Path) + } + _, _ = w.Write([]byte(`{"data":[{"id":"fixture-model"}]}`)) + })) + defer server.Close() + p := customProviderParams(t, s) + p.Definition.BaseURL, p.Credential = server.URL+"/v1/", protocol.ProviderCredential{Mode: "none"} + before, _ := config.Load() + created, err := s.CreateProvider(t.Context(), p) + if err != nil { + t.Fatal(err) + } + if requests != 1 || created.Discovery.Status != "loaded" || created.Credential.Mode != "none" || created.Credential.Available == nil || !*created.Credential.Available { + t.Fatalf("incorrect discovery/readiness: %+v, requests %d", created, requests) + } + cfg, err := config.Load() + if err != nil { + t.Fatal(err) + } + if cfg.Providers[p.Provider].Auth != "none" || cfg.DefaultModel != before.DefaultModel || cfg.DefaultProvider != before.DefaultProvider || !reflect.DeepEqual(cfg.Models, before.Models) { + t.Fatal("provider save did not preserve authentication/defaults/models") + } + restarted := NewProviderService(t.Context(), "new-generation") + defer restarted.Close() + read, err := restarted.ReadProvider(p.Provider) + if err != nil || read.Revision != created.Revision || read.Credential.Mode != "none" { + t.Fatalf("restart: %+v %v", read, err) + } + client, err := restarted.ModelClient(cfg.Providers[p.Provider]) + if err != nil || client.APIKey != "" { + t.Fatalf("no-auth model client: %v", err) + } + if _, err := s.CreateProvider(t.Context(), p); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatalf("stale create: %v", err) + } + p.Revision = read.Revision + if _, err := s.CreateProvider(t.Context(), p); err == nil { + t.Fatal("duplicate provider ID accepted") + } +} + +func TestProviderConfigurationRedactedReadAndMetadataUpdate(t *testing.T) { + s := customProviderService(t) + marker := filepath.Join(t.TempDir(), "must-not-execute") + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["custom-test"] = config.Provider{Name: "Original", BaseURL: "https://example.test/v1", APIKey: "!touch " + marker} + return nil + }) + if err != nil { + t.Fatal(err) + } + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + t.Fatal("metadata-only save performed discovery") + return nil, nil + } + read, err := s.ReadProvider("custom-test") + if err != nil { + t.Fatal(err) + } + body, _ := json.Marshal(read) + if strings.Contains(string(body), marker) || strings.Contains(string(body), "touch") || read.Credential.Mode != "command" { + t.Fatalf("secret reference exposed: %s", body) + } + updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{ + Revision: read.Revision, Provider: read.Provider, Name: new("Renamed"), + ManualModel: &protocol.ProviderManualModel{Alias: "custom-test/private-model", ID: "private-model", Context: 4096, MaxOutput: 1024}, + }) + if err != nil { + t.Fatal(err) + } + if updated.Discovery.Status != "not_checked" || len(updated.Models) != 1 || updated.Models[0].ID != "private-model" { + t.Fatalf("incorrect alias save: %+v", updated) + } + if _, err := os.Stat(marker); !os.IsNotExist(err) { + t.Fatal("read or metadata-only update executed the secret command") + } + cfg, _ := config.Load() + if cfg.Providers[read.Provider].APIKey != "!touch "+marker { + t.Fatal("name edit replaced the existing credential") + } + for _, credential := range []*protocol.ProviderCredential{nil, {Mode: "keep"}} { + _, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Revision: updated.Revision, Provider: read.Provider, BaseURL: new("https://other.test/v1"), Credential: credential}) + if err == nil || !strings.Contains(err.Error(), "explicit credential choice") { + t.Fatalf("endpoint edit forwarded old credential: %v", err) + } + } +} + +func TestProviderConfigurationUnverifiedAndAuthenticationFailures(t *testing.T) { + for _, outcome := range []string{"empty", "404", "transport", "401", "403", "missing environment"} { + t.Run(outcome, func(t *testing.T) { + s := customProviderService(t) + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + switch outcome { + case "empty": + return nil, nil + case "transport": + return nil, errors.New("private-fixture-key inside URL error") + case "missing environment": + t.Fatal("attempted request with absent environment credential") + } + return nil, &llm.HTTPError{Status: outcome + " failure", Body: "private-fixture-key echoed by upstream"} + } + p := customProviderParams(t, s) + if outcome == "missing environment" { + t.Setenv("WHIP_MISSING_PROVIDER_TEST_KEY", "") + p.Credential = protocol.ProviderCredential{Mode: "environment", EnvironmentVariable: "WHIP_MISSING_PROVIDER_TEST_KEY"} + } + if _, err := s.CreateProvider(t.Context(), p); err == nil || strings.Contains(err.Error(), "private-fixture-key") { + t.Fatalf("normal save should fail safely: %v", err) + } + p.AllowUnverified = true + p.ManualModel = &protocol.ProviderManualModel{Alias: "custom-test/exact-model", ID: "exact-model"} + result, err := s.CreateProvider(t.Context(), p) + if outcome == "401" || outcome == "403" { + if err == nil { + t.Fatal("explicit save bypassed a known authentication rejection") + } + if _, readErr := s.ReadProvider(p.Provider); readErr == nil { + t.Fatal("rejected credentials were persisted") + } + return + } + if err != nil || result.Discovery.Status != "unverified" || len(result.Models) != 1 { + t.Fatalf("unverified save: %+v %v", result, err) + } + if outcome == "missing environment" && (result.Credential.Available == nil || *result.Credential.Available) { + t.Fatal("missing environment credential is ready") + } + }) + } +} + +func TestProviderConfigurationValidationAndRemoval(t *testing.T) { + s := customProviderService(t) + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return []llm.ModelInfo{{ID: "m"}}, nil } + p := customProviderParams(t, s) + for _, id := range []string{"inference-net", "inference", "openrouter", "openai-codex", "../escape", "Invalid ID"} { + p.Provider = id + if _, err := s.CreateProvider(t.Context(), p); err == nil { + t.Fatalf("accepted ID %q", id) + } + } + p.Provider = "custom-test" + for _, endpoint := range []string{"https://key:secret@example.test/v1", "https://example.test/v1?secret=value", "https://example.test/v1#fragment", "file:///tmp/model", "https://example.test/v1/chat/completions"} { + p.Definition.BaseURL = endpoint + if _, err := s.CreateProvider(t.Context(), p); err == nil { + t.Fatalf("accepted endpoint %q", endpoint) + } + } + p.Definition.BaseURL = "https://example.test/v1" + for _, key := range []string{"!touch /tmp/whip-test-must-not-execute", "$WHIP_KEY", "${WHIP_KEY}"} { + p.Credential.Key = key + if _, err := s.CreateProvider(t.Context(), p); err == nil { + t.Fatalf("accepted reference as a literal key %q", key) + } + } + p.Credential.Key = "private-fixture-key" + result, err := s.CreateProvider(t.Context(), p) + if err != nil { + t.Fatal(err) + } + _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: "inference-net", Revision: result.Revision}) + if err == nil { + t.Fatal("removed a built-in provider") + } + _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: p.Revision}) + if !errors.Is(err, config.ErrRevisionConflict) { + t.Fatalf("stale removal: %v", err) + } + removed, err := s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: result.Revision}) + if err != nil || removed.Revision == result.Revision { + t.Fatalf("remove: %+v %v", removed, err) + } + if _, err := s.ReadProvider(p.Provider); err == nil { + t.Fatal("removed provider remains") + } + if _, exists := config.LoadCatalogs()[p.Provider]; exists { + t.Fatal("removed provider's catalog remains") + } +} + +func TestProviderConfigurationInvalidCreateLeavesSettingsUntouched(t *testing.T) { + s := customProviderService(t) + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + t.Error("invalid configuration reached model discovery") + return nil, errors.New("unexpected discovery") + } + valid := customProviderParams(t, s) + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + for _, test := range []struct { + name string + change func(*protocol.ProviderCreateParams) + }{ + {"missing display name", func(p *protocol.ProviderCreateParams) { p.Definition.Name = " " }}, + {"unsupported API", func(p *protocol.ProviderCreateParams) { p.Definition.API = "anthropic" }}, + {"keep without saved credential", func(p *protocol.ProviderCreateParams) { p.Credential = protocol.ProviderCredential{Mode: "keep"} }}, + {"empty key", func(p *protocol.ProviderCreateParams) { p.Credential.Key = " " }}, + {"header injection", func(p *protocol.ProviderCreateParams) { p.Credential.Key = "key\r\nInjected: header" }}, + {"invalid environment name", func(p *protocol.ProviderCreateParams) { + p.Credential = protocol.ProviderCredential{Mode: "environment", EnvironmentVariable: "NOT-A-VARIABLE"} + }}, + {"credential with no auth", func(p *protocol.ProviderCreateParams) { p.Credential.Mode = "none" }}, + {"unknown auth mode", func(p *protocol.ProviderCreateParams) { p.Credential.Mode = "custom" }}, + {"ambiguous model ID", func(p *protocol.ProviderCreateParams) { + p.ManualModel = &protocol.ProviderManualModel{Alias: "custom/model", ID: " model "} + }}, + {"negative model limits", func(p *protocol.ProviderCreateParams) { + p.ManualModel = &protocol.ProviderManualModel{Alias: "custom/model", ID: "model", Context: -1} + }}, + } { + t.Run(test.name, func(t *testing.T) { + params := valid + test.change(¶ms) + if _, err := s.CreateProvider(t.Context(), params); err == nil { + t.Fatal("invalid connection accepted") + } + after, err := s.ReadConfiguration() + if err != nil || !reflect.DeepEqual(after, before) { + t.Fatalf("failed create changed persisted configuration: %+v %v", after, err) + } + if _, err := s.ReadProvider(valid.Provider); err == nil { + t.Fatal("failed create left a partial connection") + } + }) + } +} + +func TestProviderOperationsFailClosedForMalformedHostConfiguration(t *testing.T) { + s := customProviderService(t) + params := customProviderParams(t, s) + directory, err := config.Dir() + if err != nil { + t.Fatal(err) + } + path := filepath.Join(directory, "config.json") + if err := os.WriteFile(path, []byte("{not valid configuration"), 0o600); err != nil { + t.Fatal(err) + } + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + t.Error("unreadable configuration initiated discovery") + return nil, errors.New("unexpected request") + } + s.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { + t.Error("unreadable configuration initiated sign-in") + return openaiauth.Credentials{}, errors.New("unexpected authorization") + } + for _, test := range []struct { + name string + call func() error + }{ + {"configuration", func() error { _, err := s.ReadConfiguration(); return err }}, + {"editable provider", func() error { _, err := s.ReadProvider("openrouter"); return err }}, + {"account status", func() error { _, err := s.ProviderStatus(openaiauth.Provider); return err }}, + {"OpenAI sign-in", func() error { _, err := s.BeginProviderLogin(openaiauth.Provider); return err }}, + {"Inference sign-in", func() error { _, err := s.BeginLogin(); return err }}, + {"create", func() error { _, err := s.CreateProvider(t.Context(), params); return err }}, + {"model client", func() error { + _, err := s.ModelClient(config.Provider{BaseURL: "https://example.test/v1", APIKey: "private-fixture-key"}) + return err + }}, + {"catalog refresh", func() error { return s.refreshCatalog(t.Context(), "openrouter", config.Provider{}) }}, + } { + t.Run(test.name, func(t *testing.T) { + if err := test.call(); err == nil { + t.Fatal("operation silently accepted malformed host configuration") + } + }) + } + if len(s.Catalogs()) != 0 || len(s.ListLogins().Flows) != 0 { + t.Fatal("unreadable configuration exposed routes or admitted authorization") + } + if err := os.Remove(path); err != nil { + t.Fatal(err) + } + if recovered, err := s.ReadConfiguration(); err != nil || recovered.Revision != params.Revision { + t.Fatalf("repaired configuration requires a daemon restart: %+v %v", recovered, err) + } +} + +func TestProviderConfigurationConcurrentEditAndCancellation(t *testing.T) { + for _, action := range []string{"edit", "cancel"} { + t.Run(action, func(t *testing.T) { + s := customProviderService(t) + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + if action == "cancel" { + cancel() + } else { + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { cfg.Theme = "light"; return nil }) + if err != nil { + t.Fatal(err) + } + } + return []llm.ModelInfo{{ID: "fixture"}}, nil + } + p := customProviderParams(t, s) + _, err := s.CreateProvider(ctx, p) + if action == "edit" && !errors.Is(err, config.ErrRevisionConflict) || action == "cancel" && !errors.Is(err, context.Canceled) { + t.Fatalf("unexpected failure: %v", err) + } + cfg, _ := config.Load() + if _, exists := cfg.Providers[p.Provider]; exists { + t.Fatal("interrupted create committed configuration") + } + if action == "edit" && cfg.Theme != "light" { + t.Fatal("concurrent config change lost") + } + }) + } +} + +func TestProviderConfigurationManualAliasOwnershipAndRemovalBlockers(t *testing.T) { + s := customProviderService(t) + s.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return []llm.ModelInfo{{ID: "fixture"}}, nil + } + p := customProviderParams(t, s) + p.ManualModel = &protocol.ProviderManualModel{Alias: "kimi-k3", ID: "other-model"} + if _, err := s.CreateProvider(t.Context(), p); err == nil { + t.Fatal("create overwrote a configured model alias") + } + p.ManualModel = &protocol.ProviderManualModel{Alias: "custom-test/fixture", ID: "fixture", Context: 8192, MaxOutput: 2048} + created, err := s.CreateProvider(t.Context(), p) + if err != nil { + t.Fatal(err) + } + if len(created.RemovalBlockers) != 1 || !strings.Contains(created.RemovalBlockers[0], "custom-test/fixture") { + t.Fatalf("missing alias blocker: %+v", created.RemovalBlockers) + } + if _, err := s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: p.Provider, Revision: created.Revision}); err == nil { + t.Fatal("removed provider referenced by alias") + } + updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: p.Provider, Revision: created.Revision, ManualModel: &protocol.ProviderManualModel{Alias: p.ManualModel.Alias, ID: "fixture", Context: 16384, MaxOutput: 4096}}) + if err != nil || len(updated.Models) != 1 || updated.Models[0].Context != 16384 { + t.Fatalf("model limit update: %+v %v", updated, err) + } + _, err = s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: p.Provider, Revision: updated.Revision, ManualModel: &protocol.ProviderManualModel{Alias: p.ManualModel.Alias, ID: "different-model"}}) + if err == nil { + t.Fatal("update replaced an alias with a different model") + } + _, _, err = config.UpdateVersioned(updated.Revision, func(cfg *config.Config) error { + cfg.DefaultProvider, cfg.CompactProvider = p.Provider, p.Provider + return nil + }) + if err != nil { + t.Fatal(err) + } + read, _ := s.ReadProvider(p.Provider) + if len(read.RemovalBlockers) != 3 { + t.Fatalf("default/compaction references missing: %v", read.RemovalBlockers) + } +} + +func TestProviderConfigurationBuiltinsAndCredentialReplacement(t *testing.T) { + s := customProviderService(t) + t.Setenv("OPENROUTER_API_KEY", "private-environment-key") + read, err := s.ReadProvider("openrouter") + if err != nil || read.Custom || read.Credential.Mode != "environment" || read.Definition.BaseURL != config.OpenRouterBaseURL { + t.Fatalf("builtin read: %+v %v", read, err) + } + s.validate = func(ctx context.Context, endpoint, key string) ([]llm.ModelInfo, error) { + if endpoint != config.OpenRouterBaseURL || key != "private-new-key" { + t.Fatal("unexpected built-in route or credential") + } + return []llm.ModelInfo{{ID: "fixture", SupportsTools: new(true), OutputModalities: []string{"text"}}}, nil + } + updated, err := s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: "openrouter", Revision: read.Revision, Credential: &protocol.ProviderCredential{Mode: "api_key", Key: "private-new-key"}}) + if err != nil || updated.Credential.Mode != "api_key" { + t.Fatalf("builtin edit: %+v %v", updated, err) + } + body, _ := json.Marshal(updated) + if strings.Contains(string(body), "private-") { + t.Fatal("save response exposed a credential") + } + cfg, _ := config.Load() + if cfg.Providers["openrouter"].APIKeyEnv != "" || cfg.Providers["openrouter"].APIKey != "private-new-key" { + t.Fatal("replacement left an environment fallback") + } + _, err = s.UpdateProvider(t.Context(), protocol.ProviderUpdateParams{Provider: "openrouter", Revision: updated.Revision, BaseURL: new("https://other.test/v1"), Credential: &protocol.ProviderCredential{Mode: "none"}}) + if err == nil { + t.Fatal("edited a built-in endpoint") + } +} + +func TestProviderConfigurationLastProviderRemovalPreservesRecoveryGuard(t *testing.T) { + s := customProviderService(t) + _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers = map[string]config.Provider{"only": {Name: "Only provider", BaseURL: "http://localhost:1234/v1", Auth: "none"}} + cfg.Models = map[string]config.Model{} + cfg.DefaultModel, cfg.DefaultProvider, cfg.CompactModel, cfg.CompactProvider = "", "", "", "" + return nil + }) + if err != nil { + t.Fatal(err) + } + _, err = s.RemoveProvider(t.Context(), protocol.ProviderRemoveParams{Provider: "only", Revision: revision}) + if err == nil || !strings.Contains(err.Error(), "Add another connection") { + t.Fatalf("missing last-provider guidance: %v", err) + } + cfg, after, err := config.ReadVersioned() + if err != nil || after != revision || len(cfg.Providers) != 1 { + t.Fatal("last-provider removal changed protected configuration") + } +} + +func TestProviderManualModelClearsLegacyLimitAndPreservesOtherFields(t *testing.T) { + cfg := &config.Config{Models: map[string]config.Model{ + "alias": {Name: "Human name", ID: "model", Providers: []string{"custom"}, Context: 4096, MaxTokens: 4096, MaxOut: 1024, Vision: true}, + "shared": {ID: "model", Providers: []string{"custom", "other"}, Context: 4096}, + }} + if err := applyManualProviderModel(cfg, "custom", &protocol.ProviderManualModel{Alias: "alias", ID: "model"}, false); err != nil { + t.Fatal(err) + } + model := cfg.Models["alias"] + if model.Context != 0 || model.MaxTokens != 0 || model.MaxOut != 0 || model.Name != "Human name" || !model.Vision { + t.Fatalf("model metadata was lost or legacy limit survived: %+v", model) + } + if err := applyManualProviderModel(cfg, "custom", &protocol.ProviderManualModel{Alias: "shared", ID: "model", Context: 8192}, false); err == nil || cfg.Models["shared"].Context != 4096 { + t.Fatal("manual model update edited a shared alias") + } +} + +func TestProviderConfigurationRedactsInvalidFileAuthoredEndpoint(t *testing.T) { + s := customProviderService(t) + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["unsafe-old-route"] = config.Provider{Name: "Old connection", BaseURL: "https://user:private-userinfo@example.test/v1?key=private-query#private-fragment", APIKey: "private-literal-key"} + return nil + }) + if err != nil { + t.Fatal(err) + } + read, err := s.ReadProvider("unsafe-old-route") + if err != nil { + t.Fatal(err) + } + encoded, _ := json.Marshal(read) + if strings.Contains(string(encoded), "private-") || read.Definition.BaseURL != "https://example.test/v1" || read.Credential.Available == nil || *read.Credential.Available { + t.Fatalf("unsafe editable metadata: %s", encoded) + } +} diff --git a/internal/provider/provider_connections_test.go b/internal/provider/provider_connections_test.go new file mode 100644 index 000000000..9b984b5d9 --- /dev/null +++ b/internal/provider/provider_connections_test.go @@ -0,0 +1,391 @@ +package provider + +import ( + "context" + "encoding/json" + "errors" + "io" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "reflect" + "slices" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/openaiauth" + "github.com/context-labs/whip/internal/protocol" +) + +func providerConnectionsFixture(t *testing.T) *ProviderService { + t.Helper() + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("HOME", t.TempDir()) + t.Setenv(config.InferenceNetEnvVar, "") + t.Setenv(config.OpenRouterEnvVar, "") + service := NewProviderService(t.Context(), "connections") + t.Cleanup(service.Close) + return service +} + +func providerEntry(t *testing.T, service *ProviderService, id string) protocol.ProviderEntry { + t.Helper() + list, err := service.ListProviders() + if err != nil { + t.Fatal(err) + } + for _, entry := range list.Providers { + if entry.ID == id { + return entry + } + } + t.Fatalf("missing provider %q", id) + return protocol.ProviderEntry{} +} + +func TestProviderInventoryReportsWinningSourceWithoutExecutingSecrets(t *testing.T) { + service := providerConnectionsFixture(t) + t.Setenv(config.OpenRouterEnvVar, "private-environment-key") + marker := filepath.Join(t.TempDir(), "executed") + cfg, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["command"] = config.Provider{BaseURL: "https://example.test/v1", APIKey: "!touch " + marker} + cfg.Providers["custom"] = config.Provider{Name: "Custom", BaseURL: "https://example.test/v1", APIKey: "private-saved-key"} + cfg.Providers["bad-url"] = config.Provider{BaseURL: "not-a-url", APIKey: "private-saved-key"} + return nil + }) + if err != nil { + t.Fatal(err) + } + before, err := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) + if err != nil { + t.Fatal(err) + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + t.Error("inventory made an upstream request") + return nil, nil + } + list, err := service.ListProviders() + if err != nil { + t.Fatal(err) + } + encoded, err := json.Marshal(list) + if err != nil || strings.Contains(string(encoded), "private-") { + t.Fatal("inventory exposed a credential") + } + for id, want := range map[string]struct { + source, state string + available bool + }{ + "inference-net": {"environment", "key_required", false}, + "openrouter": {"environment", "connected", true}, + "custom": {"literal", "connected", true}, + "command": {"command", "unchecked", false}, + "bad-url": {"literal", "configuration_error", false}, + } { + entry := providerEntry(t, service, id) + if entry.Status.KeySource != want.source || entry.Status.AuthState != want.state || entry.Status.Available == nil || *entry.Status.Available != want.available { + t.Fatalf("%s status = %+v", id, entry.Status) + } + } + if _, err := os.Stat(marker); !errors.Is(err, os.ErrNotExist) { + t.Fatal("inventory executed a secret command") + } + after, _ := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) + if string(before) != string(after) { + t.Fatal("inventory changed saved configuration") + } + if _, ok := cfg.Providers["openrouter"]; ok { + t.Fatal("discovery persisted") + } +} + +func TestProviderConnectPreservesCustomEndpointAndDefaults(t *testing.T) { + service := providerConnectionsFixture(t) + _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["openrouter"] = config.Provider{Name: "Proxy", BaseURL: "https://proxy.test/v1", API: "openai-completions", APIKeyEnv: "PROXY_TEST_KEY"} + cfg.DisabledProviders = []string{"openrouter", "unrelated"} + return nil + }) + if err != nil { + t.Fatal(err) + } + before, _ := config.Load() + service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { + if endpoint != "https://proxy.test/v1" || key != "private-new-key" { + t.Fatal("setup replaced the configured endpoint or key") + } + return []llm.ModelInfo{{ID: "fixture-model"}}, nil + } + if _, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: revision, Provider: "openrouter", Key: "private-new-key"}); err != nil { + t.Fatal(err) + } + after, _ := config.Load() + if after.DefaultModel != before.DefaultModel || after.DefaultProvider != before.DefaultProvider || !reflect.DeepEqual(after.Models, before.Models) { + t.Fatal("connect changed model defaults or aliases") + } + if after.Providers["openrouter"].Name != "Proxy" || after.Providers["openrouter"].APIKeyEnv != "" || !reflect.DeepEqual(after.DisabledProviders, []string{"unrelated"}) { + t.Fatal("connect changed route metadata or unrelated disabled entries") + } + if _, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: revision, Provider: "openrouter", Key: "private-other-key"}); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatalf("stale setup = %v", err) + } +} + +func TestProviderDisconnectRestoresDefaultSetup(t *testing.T) { + for _, environment := range []string{"", "private-environment-key"} { + t.Run(map[bool]string{true: "environment", false: "empty"}[environment != ""], func(t *testing.T) { + service := providerConnectionsFixture(t) + t.Setenv(config.OpenRouterEnvVar, environment) + before, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["openrouter"] = config.Provider{BaseURL: config.OpenRouterBaseURL, APIKey: "private-saved-key"} + cfg.DisabledProviders = []string{"openrouter", "unrelated"} + return nil + }) + if err != nil { + t.Fatal(err) + } + if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, Models: []config.ModelInfoLite{{ID: "fixture"}}}); err != nil { + t.Fatal(err) + } + status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}) + if err != nil || status.Disabled || status.Available == nil || *status.Available != (environment != "") { + t.Fatalf("disconnect = %+v, %v", status, err) + } + cfg, err := config.Load() + if err != nil || cfg.Providers["openrouter"].APIKey != "" || cfg.Providers["openrouter"].APIKeyEnv != config.OpenRouterEnvVar || cfg.DefaultModel != before.DefaultModel || !reflect.DeepEqual(cfg.Models, before.Models) || !reflect.DeepEqual(cfg.DisabledProviders, []string{"unrelated"}) { + t.Fatal("disconnect did not restore setup while preserving unrelated config") + } + if _, exists := config.LoadCatalogs()["openrouter"]; exists { + t.Fatal("disconnect retained cache") + } + restarted := NewProviderService(t.Context(), "restarted") + t.Cleanup(restarted.Close) + reloaded := providerEntry(t, restarted, "openrouter").Status + if reloaded.Disabled || reloaded.Available == nil || *reloaded.Available != (environment != "") { + t.Fatal("restart changed reset state") + } + if _, err := restarted.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatal("stale disconnect accepted") + } + }) + } +} + +func TestProviderDisconnectClearsPreviousAccountBehindAnAPIKey(t *testing.T) { + service := providerConnectionsFixture(t) + if err := inferencenet.SaveAuth(inferencenet.Auth{MachineKey: "old-account-key", TeamName: "Old team"}); err != nil { + t.Fatal(err) + } + _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: config.InferenceNetBaseURL, APIKey: "saved-key"} + return nil + }) + if err != nil { + t.Fatal(err) + } + status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: config.InferenceNetProvider, Revision: revision}) + if err != nil || status.Disabled || status.Available == nil || *status.Available { + t.Fatalf("disconnect = %+v, %v", status, err) + } + auth, err := inferencenet.LoadAuth() + if err != nil || auth != (inferencenet.Auth{}) { + t.Fatal("old account survived disconnect") + } +} + +func TestProviderEnvironmentDisablePreservesKeysAndInterruptsLogin(t *testing.T) { + service := providerConnectionsFixture(t) + t.Setenv(config.OpenRouterEnvVar, "private-environment-key") + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + if _, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: before.Revision}); err == nil { + t.Fatal("allowed removing an external credential") + } + ready := make(chan struct{}) + service.openAILogin = func(ctx context.Context, _ func(string, string)) (openaiauth.Credentials, error) { + close(ready) + <-ctx.Done() + return openaiauth.Credentials{}, ctx.Err() + } + flow, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + <-ready + disabled := []string{"openrouter", openaiauth.Provider} + updated, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DisabledProviders: &disabled}) + if err != nil { + t.Fatal(err) + } + if state, _ := service.LoginStatus(flow.FlowID); state.State != "interrupted" { + t.Fatal("disable left login able to reconnect provider") + } + if os.Getenv(config.OpenRouterEnvVar) != "private-environment-key" { + t.Fatal("disable changed environment") + } + if _, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DisabledProviders: new([]string{})}); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatal("stale enable accepted") + } + if _, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: updated.Revision, DisabledProviders: new([]string{})}); err != nil { + t.Fatal(err) + } + if !*providerEntry(t, service, "openrouter").Status.Available { + t.Fatal("enable did not restore environment route") + } +} + +func TestProviderDisabledDuringCatalogFetchCannotRepublishModels(t *testing.T) { + service := providerConnectionsFixture(t) + started, release := make(chan struct{}), make(chan struct{}) + upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + close(started) + <-release + _, _ = w.Write([]byte(`{"data":[{"id":"fixture-model"}]}`)) + })) + t.Cleanup(upstream.Close) + cfg, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["custom"] = config.Provider{BaseURL: upstream.URL, APIKey: "fixture"} + return nil + }) + if err != nil { + t.Fatal(err) + } + done := make(chan error, 1) + go func() { done <- service.refreshCatalog(t.Context(), "custom", cfg.Providers["custom"]) }() + <-started + disabled := []string{"custom"} + _, disableErr := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: revision, DisabledProviders: &disabled}) + close(release) + if disableErr != nil { + t.Fatal(disableErr) + } + select { + case err := <-done: + if err == nil { + t.Fatal("late catalog was accepted") + } + case <-time.After(3 * time.Second): + t.Fatal("catalog fetch did not finish") + } + if _, exists := service.Catalogs()["custom"]; exists { + t.Fatal("disabled models republished") + } +} + +func TestProviderInferenceLoginPreservesCustomOverride(t *testing.T) { + service := providerConnectionsFixture(t) + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "fixture"} + return nil + }) + if err != nil { + t.Fatal(err) + } + entry := providerEntry(t, service, config.InferenceNetProvider) + if !entry.Custom || slices.Contains(entry.Methods, "login") { + t.Fatal("custom endpoint advertised account login") + } + if _, err := service.BeginLogin(); err == nil { + t.Fatal("account login accepted a custom endpoint") + } +} + +func TestProviderCustomDisconnectLeavesUnrelatedAccountIntact(t *testing.T) { + service := providerConnectionsFixture(t) + auth := inferencenet.Auth{MachineKey: "private-unrelated-machine-key"} + if err := inferencenet.SaveAuth(auth); err != nil { + t.Fatal(err) + } + _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers[config.InferenceNetProvider] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "private-custom-key"} + return nil + }) + if err != nil { + t.Fatal(err) + } + if _, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: config.InferenceNetProvider, Revision: revision}); err != nil { + t.Fatal(err) + } + retained, err := inferencenet.LoadAuth() + if err != nil || retained.MachineKey != auth.MachineKey { + t.Fatal("custom disconnect removed unrelated account") + } +} + +type providerFixtureTransport func(*http.Request) (*http.Response, error) + +func (f providerFixtureTransport) RoundTrip(request *http.Request) (*http.Response, error) { + return f(request) +} + +func TestProviderAccountReplacementCannotRepublishOldCatalog(t *testing.T) { + service := providerConnectionsFixture(t) + if err := inferencenet.SaveAuth(inferencenet.Auth{MachineKey: "private-old-machine-key"}); err != nil { + t.Fatal(err) + } + cfg, err := config.Load() + if err != nil { + t.Fatal(err) + } + started, release := make(chan struct{}), make(chan struct{}) + previous := http.DefaultTransport + http.DefaultTransport = providerFixtureTransport(func(request *http.Request) (*http.Response, error) { + if request.URL.String() != config.InferenceNetBaseURL+"/models" || request.Header.Get("Authorization") != "Bearer private-old-machine-key" { + t.Error("unexpected fixture provider request") + } + close(started) + select { + case <-release: + case <-request.Context().Done(): + return nil, request.Context().Err() + } + return &http.Response{StatusCode: http.StatusOK, Header: http.Header{}, Body: io.NopCloser(strings.NewReader(`{"data":[{"id":"old-account-model"}]}`))}, nil + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + done := make(chan error, 1) + go func() { + done <- service.refreshCatalog(t.Context(), config.InferenceNetProvider, cfg.Providers[config.InferenceNetProvider]) + }() + <-started + service.provisionMu.Lock() + err = service.finish(t.Context(), inferencenet.Auth{MachineKey: "private-new-machine-key"}) + service.provisionMu.Unlock() + close(release) + if err != nil { + t.Fatal(err) + } + if err := <-done; err == nil { + t.Fatal("old account catalog was accepted after replacement") + } + if _, exists := config.LoadCatalogs()[config.InferenceNetProvider]; exists { + t.Fatal("old account models survived replacement") + } +} + +func TestProviderResetLegacyDisabledEnvironmentPreservesSource(t *testing.T) { + service := providerConnectionsFixture(t) + t.Setenv(config.OpenRouterEnvVar, "environment-key") + _, revision, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["openrouter"] = config.Provider{BaseURL: config.OpenRouterBaseURL, APIKeyEnv: config.OpenRouterEnvVar} + cfg.DisabledProviders = []string{"openrouter", "unrelated"} + return nil + }) + if err != nil { + t.Fatal(err) + } + status, err := service.DisconnectProvider(t.Context(), protocol.ProviderDisconnectParams{Provider: "openrouter", Revision: revision}) + if err != nil || status.Disabled || status.Available == nil || !*status.Available { + t.Fatalf("reset = %+v, %v", status, err) + } + cfg, err := config.Load() + if err != nil || cfg.Providers["openrouter"].APIKeyEnv != config.OpenRouterEnvVar || os.Getenv(config.OpenRouterEnvVar) != "environment-key" || !reflect.DeepEqual(cfg.DisabledProviders, []string{"unrelated"}) { + t.Fatal("reset changed external credentials or unrelated providers") + } +} diff --git a/internal/daemon/provider_disconnect.go b/internal/provider/provider_disconnect.go similarity index 79% rename from internal/daemon/provider_disconnect.go rename to internal/provider/provider_disconnect.go index fa4cffdd9..c286e648d 100644 --- a/internal/daemon/provider_disconnect.go +++ b/internal/provider/provider_disconnect.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" @@ -13,31 +13,31 @@ import ( // DisconnectProvider clears WHIP-owned credentials and restores normal provider // setup. Credentials managed outside WHIP remain in their original sources. -func (s *ProviderService) DisconnectProvider(ctx context.Context, p protocol.ProviderDisconnectParams) (ProviderStatus, error) { +func (s *ProviderService) DisconnectProvider(ctx context.Context, p protocol.ProviderDisconnectParams) (protocol.ProviderStatus, error) { if p.Revision == "" { - return ProviderStatus{}, errors.New("configuration revision is required") + return protocol.ProviderStatus{}, errors.New("configuration revision is required") } s.provisionMu.Lock() defer s.provisionMu.Unlock() if err := ctx.Err(); err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } cfg, revision, err := config.ReadVersioned() if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } if revision != p.Revision { - return ProviderStatus{}, config.ErrRevisionConflict + return protocol.ProviderStatus{}, config.ErrRevisionConflict } status, err := s.providerStatus(cfg, p.Provider) if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } switch status.KeySource { case "literal", "machine", "subscription": default: if !status.Disabled { - return ProviderStatus{}, errors.New("credentials are managed outside Whip; remove them at their source to disconnect") + return protocol.ProviderStatus{}, errors.New("credentials are managed outside Whip; remove them at their source to disconnect") } } inferenceAccount := p.Provider == config.InferenceNetProvider && status.KeySource == "machine" @@ -61,7 +61,7 @@ func (s *ProviderService) DisconnectProvider(ctx context.Context, p protocol.Pro return nil }) if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } // Cancel only after the revision is accepted, so stale UI cannot interrupt login. s.interruptProviderLogins(p.Provider) @@ -69,7 +69,7 @@ func (s *ProviderService) DisconnectProvider(ctx context.Context, p protocol.Pro return s.logoutOpenAILocked(ctx) } if err := config.DeleteCatalog(p.Provider); err != nil { - return ProviderStatus{}, errors.New("saved credentials removed, but the provider model cache could not be removed") + return protocol.ProviderStatus{}, errors.New("saved credentials removed, but the provider model cache could not be removed") } if inferenceAccount { return s.logoutInferenceNetLocked(ctx) diff --git a/internal/daemon/provider_discovery.go b/internal/provider/provider_discovery.go similarity index 98% rename from internal/daemon/provider_discovery.go rename to internal/provider/provider_discovery.go index 9af087275..c8e874ab3 100644 --- a/internal/daemon/provider_discovery.go +++ b/internal/provider/provider_discovery.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" diff --git a/internal/provider/provider_discovery_test.go b/internal/provider/provider_discovery_test.go new file mode 100644 index 000000000..6afb1e676 --- /dev/null +++ b/internal/provider/provider_discovery_test.go @@ -0,0 +1,151 @@ +package provider + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/llm" +) + +func TestDiscoveredFileKeyPersistsReferenceAndReachesInference(t *testing.T) { + service := pickerInventoryFixture(t) + filename := filepath.Join(t.TempDir(), "providers.env") + writeKey := func(value string) { + t.Helper() + if err := os.WriteFile(filename, []byte("OPENROUTER_API_KEY="+value+"\n"), 0o600); err != nil { + t.Fatal(err) + } + } + writeKey("fixture-file-key") + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.ProviderKeySources.EnvFiles = []string{filename} + return nil + }) + if err != nil { + t.Fatal(err) + } + before := providerEntry(t, service, "openrouter") + if before.Status.Configured || !*before.Status.Available || before.Status.KeySource != "env_file" { + t.Fatal("read-only inventory did not resolve a file-backed key") + } + list, err := service.DiscoverProviders(t.Context(), "", "") + if err != nil || list.DiscoveryError != "" { + t.Fatalf("discovery: %v %s", err, list.DiscoveryError) + } + entry := providerEntry(t, service, "openrouter") + if !entry.Status.Configured || entry.Status.CredentialPath != filename || entry.Status.EnvironmentVariable != "OPENROUTER_API_KEY" { + t.Fatal("discovery did not persist the named reference and provenance") + } + managed, err := service.ReadProvider("openrouter") + if err != nil || managed.Credential.Mode != "environment" || managed.Credential.CredentialPath != filename { + t.Fatal("management lost the editable named reference") + } + data, err := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) + if err != nil || strings.Contains(string(data), "fixture-file-key") { + t.Fatal("configuration persisted resolved credential material") + } + encoded, err := json.Marshal(list) + if err != nil || strings.Contains(string(encoded), "fixture-file-key") { + t.Fatal("provider inventory exposed resolved credential material") + } + second, err := service.DiscoverProviders(t.Context(), "", "") + if err != nil || second.Revision != list.Revision { + t.Fatal("no-op discovery changed the revision") + } + unchanged, _ := os.ReadFile(filepath.Join(os.Getenv("WHIPCODE_HOME"), "config.json")) + if string(unchanged) != string(data) { + t.Fatal("no-op discovery rewrote configuration") + } + + expectedKey := "fixture-file-key" + var paths []string + previous := http.DefaultTransport + http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { + if r.URL.Host != "openrouter.ai" || r.Header.Get("Authorization") != "Bearer "+expectedKey { + t.Fatal("file credential did not reach the expected provider") + } + paths = append(paths, r.URL.Path) + body := `{"data":{"label":"fixture"}}` + switch r.URL.Path { + case "/api/v1/key": + case "/api/v1/models": + body = `{"data":[{"id":"new-live-model"}]}` + case "/api/v1/chat/completions": + body = "data: {\"choices\":[{\"delta\":{\"content\":\"hello\"}}]}\n\ndata: [DONE]\n\n" + default: + t.Fatal("unexpected provider request") + } + return &http.Response{StatusCode: http.StatusOK, Status: "200 OK", Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + for _, key := range []string{"fixture-file-key", "fixture-rotated-key"} { + writeKey(key) + expectedKey = key + // A new owner/constructor rereads references after a restart or reload. + restarted := NewProviderService(t.Context(), key) + cfg, loadErr := config.Load() + if loadErr != nil { + t.Fatal(loadErr) + } + provider := cfg.Providers["openrouter"] + if err := restarted.refreshCatalog(t.Context(), "openrouter", provider); err != nil { + t.Fatal(err) + } + catalog := restarted.Catalogs()["openrouter"] + if len(catalog.Models) != 1 || catalog.Models[0].ID != "new-live-model" { + t.Fatal("bundled catalog replaced live membership") + } + client, err := restarted.ModelClient(provider) + if err != nil { + t.Fatal(err) + } + message, _, err := client.Stream(t.Context(), llm.Request{Model: "new-live-model"}, nil, nil, nil) + restarted.Close() + if err != nil || message.Content != "hello" { + t.Fatalf("file-key inference: %v", err) + } + } + if len(paths) != 6 { + t.Fatal("expected authenticated discovery followed by inference on each construction") + } + if err := os.Remove(filename); err != nil { + t.Fatal(err) + } + entry = providerEntry(t, service, "openrouter") + if !entry.Status.Configured || *entry.Status.Available || len(entry.Status.Warnings) == 0 { + t.Fatal("removed key source must retain its route with recovery information") + } +} + +func TestDiscoveredOpenRouterKeyStillRequiresAuthentication(t *testing.T) { + service := pickerInventoryFixture(t) + t.Setenv("OPENROUTER_API_KEY", "fixture-invalid-key") + if _, err := service.DiscoverProviders(t.Context(), "", ""); err != nil { + t.Fatal(err) + } + previous := http.DefaultTransport + http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { + if r.URL.Path != "/api/v1/key" { + t.Fatal("public catalog fetched before rejecting the credential") + } + return &http.Response{StatusCode: http.StatusUnauthorized, Status: fmt.Sprintf("%d Unauthorized", 401), Body: io.NopCloser(strings.NewReader("fixture-invalid-key"))}, nil + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + cfg, err := config.Load() + if err != nil { + t.Fatal(err) + } + if err := service.refreshCatalog(t.Context(), "openrouter", cfg.Providers["openrouter"]); err == nil || strings.Contains(err.Error(), "fixture-invalid-key") { + t.Fatal("discovered invalid key was accepted or exposed") + } + if len(service.Catalogs()) != 0 { + t.Fatal("failed authentication populated a bundled model catalog") + } +} diff --git a/internal/daemon/provider_error.go b/internal/provider/provider_error.go similarity index 98% rename from internal/daemon/provider_error.go rename to internal/provider/provider_error.go index 05a7bb3e9..e5e204a16 100644 --- a/internal/daemon/provider_error.go +++ b/internal/provider/provider_error.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" diff --git a/internal/daemon/provider_error_test.go b/internal/provider/provider_error_test.go similarity index 98% rename from internal/daemon/provider_error_test.go rename to internal/provider/provider_error_test.go index cddca7339..6f07205cf 100644 --- a/internal/daemon/provider_error_test.go +++ b/internal/provider/provider_error_test.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" diff --git a/internal/daemon/provider_list.go b/internal/provider/provider_list.go similarity index 93% rename from internal/daemon/provider_list.go rename to internal/provider/provider_list.go index 8e4d9209a..9d8ef2d7b 100644 --- a/internal/daemon/provider_list.go +++ b/internal/provider/provider_list.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "cmp" @@ -113,18 +113,18 @@ func (s *ProviderService) ListProvidersFor(model, provider string) (protocol.Pro return result, nil } -func unavailableProvider(id, warning string) ProviderStatus { - return ProviderStatus{ +func unavailableProvider(id, warning string) protocol.ProviderStatus { + return protocol.ProviderStatus{ Provider: id, KeySource: "none", Available: new(false), AuthState: "configuration_error", Warnings: []string{warning}, } } -func (s *ProviderService) providerStatus(cfg *config.Config, name string) (ProviderStatus, error) { +func (s *ProviderService) providerStatus(cfg *config.Config, name string) (protocol.ProviderStatus, error) { return s.providerStatusWithCredentials(cfg, name, nil) } -func (s *ProviderService) providerStatusWithCredentials(cfg *config.Config, name string, credentials *config.CredentialSnapshot) (ProviderStatus, error) { +func (s *ProviderService) providerStatusWithCredentials(cfg *config.Config, name string, credentials *config.CredentialSnapshot) (protocol.ProviderStatus, error) { if name == openaiauth.Provider { if s == nil || s.openAI == nil { return unavailableProvider(name, "Subscription credentials are unavailable on this host."), nil @@ -134,11 +134,11 @@ func (s *ProviderService) providerStatusWithCredentials(cfg *config.Config, name return providerKeyStatusWithCredentials(cfg, name, credentials) } -func providerKeyStatus(cfg *config.Config, name string) (ProviderStatus, error) { +func providerKeyStatus(cfg *config.Config, name string) (protocol.ProviderStatus, error) { return providerKeyStatusWithCredentials(cfg, name, nil) } -func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentials *config.CredentialSnapshot) (ProviderStatus, error) { +func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentials *config.CredentialSnapshot) (protocol.ProviderStatus, error) { if credentials == nil { credentials = config.DiscoverCredentials(cfg) } @@ -152,12 +152,12 @@ func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentia } } if !found { - return ProviderStatus{}, errors.New("unknown provider") + return protocol.ProviderStatus{}, errors.New("unknown provider") } } key := credentials.KeyStatus(entry) disabled := slices.Contains(cfg.DisabledProviders, name) - result := ProviderStatus{ + result := protocol.ProviderStatus{ Provider: name, Configured: configured, KeySource: key.Source, Disabled: disabled, Available: new(key.Available && !disabled), EnvironmentVariable: key.Environment, CredentialPath: key.Path, @@ -185,7 +185,7 @@ func providerKeyStatusWithCredentials(cfg *config.Config, name string, credentia if name == config.InferenceNetProvider && key.Source == "machine" { auth, err := inferencenet.LoadAuth() if err != nil { - return ProviderStatus{}, errors.New("could not read provider account on execution host") + return protocol.ProviderStatus{}, errors.New("could not read provider account on execution host") } result.Email, result.TeamName, result.ProjectID = auth.UserEmail, auth.TeamName, auth.ProjectID result.ProjectName, result.MachineKeyName = auth.ProjectName, auth.MachineKeyName diff --git a/internal/provider/provider_list_test.go b/internal/provider/provider_list_test.go new file mode 100644 index 000000000..cae0b2d91 --- /dev/null +++ b/internal/provider/provider_list_test.go @@ -0,0 +1,103 @@ +package provider + +import ( + "os" + "path/filepath" + "slices" + "testing" + + "github.com/context-labs/whip/internal/config" +) + +func pickerInventoryFixture(t *testing.T) *ProviderService { + t.Helper() + service := providerConnectionsFixture(t) + t.Chdir(t.TempDir()) + t.Setenv("XDG_DATA_HOME", t.TempDir()) + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + for _, name := range []string{"OPENAI_BASE_URL", "OPENAI_API_BASE", "WHIP_OPENCODE_ROUTING_OVERRIDE", "OPENCODE_CONFIG", "OPENCODE_CONFIG_DIR", "OPENCODE_CONFIG_CONTENT", "OPENCODE_DB", "OPENCODE_TEST_HOME", "OPENCODE_TEST_MANAGED_CONFIG_DIR"} { + t.Setenv(name, "") + } + for _, preset := range config.ProviderPresets() { + for _, name := range preset.EnvironmentVariables { + t.Setenv(name, "") + } + } + return service +} + +func TestProviderListPresetMetadataAndEndpointCollisions(t *testing.T) { + service := pickerInventoryFixture(t) + list, err := service.ListProviders() + if err != nil || len(list.Providers) != 11 { + t.Fatalf("inventory: %v", err) + } + for _, id := range []string{"openai", "openai-codex"} { + entry := providerEntry(t, service, id) + if entry.Family != "openai" || entry.Category != "popular" { + t.Fatal("OpenAI execution routes omitted their display family") + } + } + entry := providerEntry(t, service, "groq") + if entry.Category != "providers" || entry.KeyURL == "" || entry.Custom || !slices.Equal(entry.Methods, []string{"api_key"}) { + t.Fatal("preset omitted its single-key presentation metadata") + } + _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers["openai"] = config.Provider{Name: "Existing proxy", BaseURL: "https://proxy.example/v1", APIKey: "private-proxy-key"} + return nil + }) + if err != nil { + t.Fatal(err) + } + entry = providerEntry(t, service, "openai") + if !entry.Custom || entry.Family != "" || entry.KeyURL != "" || entry.Name != "Existing proxy" { + t.Fatal("new preset hid the saved custom route") + } +} + +func TestProviderListIgnoresOpenCodeKeys(t *testing.T) { + service := pickerInventoryFixture(t) + directory := filepath.Join(os.Getenv("XDG_DATA_HOME"), "opencode") + if err := os.MkdirAll(directory, 0o700); err != nil { + t.Fatal(err) + } + filename := filepath.Join(directory, "auth.json") + auth := []byte(`{"groq":{"type":"api","key":"private-opencode-fixture"}}`) + if err := os.WriteFile(filename, auth, 0o600); err != nil { + t.Fatal(err) + } + entry := providerEntry(t, service, "groq") + if entry.Status.Configured || entry.Status.Available == nil || *entry.Status.Available { + t.Fatal("OpenCode credentials created an available connection") + } + if _, err := service.DiscoverProviders(t.Context(), "", ""); err != nil { + t.Fatal(err) + } + entry = providerEntry(t, service, "groq") + if entry.Status.Configured || *entry.Status.Available { + t.Fatal("discovery imported OpenCode credentials") + } + unchanged, err := os.ReadFile(filename) + if err != nil || string(unchanged) != string(auth) { + t.Fatal("Whip modified OpenCode credentials") + } +} + +func TestProviderListEnvironmentAliasesAndOpenAIRouting(t *testing.T) { + service := pickerInventoryFixture(t) + t.Setenv("DEEPINFRA_TOKEN", "private-alias-fixture") + t.Setenv("OPENAI_API_KEY", "private-openai-fixture") + t.Setenv("OPENAI_BASE_URL", "https://proxy.example/v1") + entry := providerEntry(t, service, "deepinfra") + if entry.Status.EnvironmentVariable != "DEEPINFRA_TOKEN" || entry.Status.Available == nil || !*entry.Status.Available { + t.Fatal("DeepInfra alias not detected") + } + entry = providerEntry(t, service, "openai") + if entry.Status.Available == nil || *entry.Status.Available || slices.Contains(entry.Methods, "environment") { + t.Fatal("OpenAI key was offered for a conflicting destination") + } + entry = providerEntry(t, service, "openai-codex") + if entry.Status.Available != nil && *entry.Status.Available { + t.Fatal("API key was interpreted as ChatGPT subscription credentials") + } +} diff --git a/internal/daemon/provider_model.go b/internal/provider/provider_model.go similarity index 99% rename from internal/daemon/provider_model.go rename to internal/provider/provider_model.go index e571ec3a4..cfc0d3ef8 100644 --- a/internal/daemon/provider_model.go +++ b/internal/provider/provider_model.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" diff --git a/internal/provider/provider_model_test.go b/internal/provider/provider_model_test.go new file mode 100644 index 000000000..f999cb9a2 --- /dev/null +++ b/internal/provider/provider_model_test.go @@ -0,0 +1,477 @@ +package provider + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "net/http" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/openaiauth" + "github.com/context-labs/whip/internal/protocol" +) + +func TestPresetDiscoveryFallbackAndPublicCatalog(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "fixture") + defer service.Close() + for _, preset := range config.ProviderPresets() { + if preset.ID == openaiauth.Provider { + continue + } + t.Run(preset.ID, func(t *testing.T) { + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &net.DNSError{Err: "network unavailable private-key"} + } + models, discovery, err := service.discoverProviderModels(t.Context(), preset.ID, preset.Provider, "fake-key") + if err != nil || len(models) == 0 || discovery.Status != "unverified" || !strings.Contains(discovery.Message, "bundled") || strings.Contains(discovery.Message, "private-key") { + t.Fatalf("fallback: %+v %+v %v", models, discovery, err) + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return []llm.ModelInfo{{ID: models[0].ID}}, nil + } + _, discovery, err = service.discoverProviderModels(t.Context(), preset.ID, preset.Provider, "fake-key") + want := "loaded" + if preset.ID == "deepinfra" { + want = "unverified" + } + if err != nil || discovery.Status != want { + t.Fatalf("loaded: %+v %v", discovery, err) + } + }) + } +} + +type catalogTransport func(*http.Request) (*http.Response, error) + +func (f catalogTransport) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } + +func TestOpenRouterSetupAuthenticatesBeforeSavingKey(t *testing.T) { + for _, status := range []int{http.StatusUnauthorized, http.StatusForbidden, http.StatusOK} { + t.Run(http.StatusText(status), func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + cfg := config.Default() + cfg.UpsertOpenRouter("previous-key", false) + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + service := NewProviderService(t.Context(), "auth-fixture") + defer service.Close() + var paths []string + previous := http.DefaultTransport + http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { + if r.URL.Host != "openrouter.ai" || r.Header.Get("Authorization") != "Bearer submitted-key" { + t.Fatal("incorrect authentication destination or credential") + } + paths = append(paths, r.URL.Path) + code, body := http.StatusOK, `{"data":[{"id":"z-ai/glm-5.3"}]}` + switch r.URL.Path { + case "/api/v1/key": + if r.Method != http.MethodGet { + t.Fatal("credential validation must be read-only") + } + code, body = status, `{"data":{"label":"redacted"}}` + if status != http.StatusOK { + body = `{"error":{"message":"Missing Authentication header submitted-key"}}` + } + case "/api/v1/models": + // This public endpoint succeeds even when the key is invalid. + case "/api/v1/chat/completions": + body = "data: {\"choices\":[{\"delta\":{\"content\":\"hello\"}}]}\n\ndata: [DONE]\n\n" + default: + t.Fatal("unexpected provider request") + } + return &http.Response{StatusCode: code, Status: fmt.Sprintf("%d %s", code, http.StatusText(code)), Header: http.Header{}, Body: io.NopCloser(strings.NewReader(body))}, nil + }) + t.Cleanup(func() { http.DefaultTransport = previous }) + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + result, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "submitted-key"}) + if status != http.StatusOK { + if err == nil || !strings.Contains(err.Error(), "API key") || strings.Contains(err.Error(), "submitted-key") { + t.Fatalf("invalid key accepted or exposed: %v", err) + } + after, readErr := service.ReadConfiguration() + if readErr != nil || after.Revision != before.Revision || len(config.LoadCatalogs()) != 0 { + t.Fatal("rejected credential changed configuration or cached the public catalog") + } + if strings.Join(paths, ",") != "/api/v1/key" { + t.Fatalf("invalid key reached model discovery: %v", paths) + } + return + } + if err != nil || result.Discovery == nil || result.Discovery.ModelCount != 1 || result.Discovery.Status != "loaded" { + t.Fatalf("valid key did not connect: %+v %v", result.Discovery, err) + } + cfg, err = config.Load() + if err != nil { + t.Fatal(err) + } + client, err := service.ModelClient(cfg.Providers["openrouter"]) + if err != nil { + t.Fatal(err) + } + message, _, err := client.Stream(t.Context(), llm.Request{Model: "z-ai/glm-5.3"}, nil, nil, nil) + if err != nil || message.Content != "hello" || strings.Join(paths, ",") != "/api/v1/key,/api/v1/models,/api/v1/chat/completions" { + t.Fatalf("saved credential did not reach inference: %v %v", paths, err) + } + }) + } +} + +func TestProviderValidationKeepsCustomAndOtherRoutesOnModels(t *testing.T) { + previous := http.DefaultTransport + t.Cleanup(func() { http.DefaultTransport = previous }) + for _, baseURL := range []string{ + "https://openrouter.ai/custom/v1", + "https://openrouter.ai.example.test/api/v1", + "https://api.cerebras.ai/v1", + } { + t.Run(baseURL, func(t *testing.T) { + calls := 0 + http.DefaultTransport = catalogTransport(func(r *http.Request) (*http.Response, error) { + calls++ + if r.URL.String() != baseURL+"/models" || r.Method != http.MethodGet || r.Header.Get("Authorization") != "Bearer fixture-key" { + t.Fatal("route used an unrelated credential check") + } + return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(`{"data":[{"id":"chat-model"}]}`))}, nil + }) + models, err := validateProviderModels(t.Context(), baseURL, "fixture-key") + if err != nil || len(models) != 1 || calls != 1 { + t.Fatalf("model discovery changed: %v (%d requests)", err, calls) + } + }) + } +} + +func TestCerebrasLiveCatalogConnectRefreshAndRestart(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "catalog-fixture") + defer service.Close() + // Cerebras documents this sparse /v1/models shape. Include a future model + // to ensure this test cannot be fixed by just extending the bundled subset. + body := `{"data":[{"id":"gpt-oss-120b"},{"id":"qwen-3.8-27b"},{"id":"future-chat-model"}]}` + calls := 0 + service.validate = func(ctx context.Context, baseURL, key string) ([]llm.ModelInfo, error) { + client := llm.New(baseURL, key) + client.HTTP = &http.Client{Transport: catalogTransport(func(r *http.Request) (*http.Response, error) { + calls++ + if r.Method != http.MethodGet || r.URL.String() != "https://api.cerebras.ai/v1/models" || r.Header.Get("Authorization") != "Bearer fixture-key" { + t.Fatal("incorrect discovery destination or authentication") + } + return &http.Response{ + StatusCode: http.StatusOK, Status: "200 OK", Header: http.Header{}, + Body: io.NopCloser(strings.NewReader(body)), + }, nil + })} + return client.Models(ctx) + } + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + connected, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{ + Revision: before.Revision, Provider: "cerebras", Key: "fixture-key", + }) + if err != nil || connected.Discovery == nil || connected.Discovery.ModelCount != 3 || calls != 1 { + t.Fatalf("key connection lost live models: %+v %v (%d requests)", connected, err, calls) + } + want := []string{"gpt-oss-120b", "qwen-3.8-27b", "future-chat-model"} + read := func(refresh bool, wantCalls int) { + t.Helper() + result, err := service.ListCatalogs(t.Context(), refresh, "cerebras") + if err != nil { + t.Fatal(err) + } + got := []string{} + for _, model := range result.Catalogs["cerebras"].Models { + got = append(got, model.ID) + } + if !reflect.DeepEqual(got, want) || calls != wantCalls || len(result.Errors) != 0 { + t.Fatalf("picker catalog = %v, errors %v, requests %d (want %v, %d)", got, result.Errors, calls, want, wantCalls) + } + } + read(false, 1) + restarted := NewProviderService(t.Context(), "restarted-catalog-fixture") + defer restarted.Close() + restarted.validate = service.validate + service = restarted + read(false, 1) + // An old binary cached a truncated list moments ago. Normal reads must + // refresh it once, even though its 24-hour TTL has not elapsed. + legacy := config.LoadCatalogs() + old := legacy["cerebras"] + old.DiscoveryVersion = 0 + old.Models = old.Models[:1] + legacy["cerebras"] = old + if err := config.SaveCatalogs(legacy); err != nil { + t.Fatal(err) + } + read(false, 2) + read(false, 2) + body = `{"data":[{"id":"qwen-3.8-27b"},{"id":"newly-released-model"}]}` + want = []string{"qwen-3.8-27b", "newly-released-model"} + read(true, 3) + read(false, 3) + stale := config.LoadCatalogs()["cerebras"] + stale.FetchedAt = time.Now().Add(-25 * time.Hour) + if err := config.UpdateCatalog("cerebras", stale); err != nil { + t.Fatal(err) + } + read(false, 4) + // A transient outage must not replace the last live list with one bundled + // model or mark the old cache as newly fetched. + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &net.DNSError{Err: "offline"} + } + prior := config.LoadCatalogs()["cerebras"] + cfg, _ := config.Load() + if err := service.refreshCatalog(t.Context(), "cerebras", cfg.Providers["cerebras"]); err == nil { + t.Fatal("outage was reported as fresh discovery") + } + if got := config.LoadCatalogs()["cerebras"]; !reflect.DeepEqual(got, prior) { + t.Fatalf("outage replaced live cache: %+v", got) + } +} + +func TestEmptyLiveCatalogDoesNotInsertBundledModels(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "catalog-fixture") + defer service.Close() + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return nil, nil } + provider := config.Provider{BaseURL: "https://api.cerebras.ai/v1", API: "openai-completions"} + models, _, err := service.discoverProviderModels(t.Context(), "cerebras", provider, "fixture-key") + if !errors.Is(err, errNoCompatibleProviderModels) || len(models) != 0 { + t.Fatalf("empty live list was replaced by bundled models: %+v %v", models, err) + } +} + +func TestPresetDiscoveryDoesNotBypassRejectionOrCustomRoute(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "fixture") + defer service.Close() + provider := config.Provider{BaseURL: config.OpenRouterBaseURL, API: "openai-completions"} + for _, status := range []string{"400 Bad Request", "401 Unauthorized", "402 Payment Required", "403 Forbidden", "429 Too Many Requests"} { + t.Run(status, func(t *testing.T) { + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &llm.HTTPError{Status: status} + } + models, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key") + if err == nil || len(models) != 0 { + t.Fatalf("rejection bypassed: %+v %v", models, err) + } + }) + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { return nil, context.Canceled } + if _, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key"); !errors.Is(err, context.Canceled) { + t.Fatalf("cancel: %v", err) + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &net.DNSError{Err: "offline"} + } + provider.BaseURL += "/custom" + if _, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key"); err == nil { + t.Fatal("custom endpoint inherited bundled catalog") + } + provider.BaseURL = config.OpenRouterBaseURL + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return []llm.ModelInfo{{ID: "audio", SupportsTools: new(false), OutputModalities: []string{"audio"}}}, nil + } + models, _, err := service.discoverProviderModels(t.Context(), "openrouter", provider, "fake-key") + if !errors.Is(err, errNoCompatibleProviderModels) || len(models) != 0 || !errors.Is(providerValidationError(err), errNoCompatibleProviderModels) { + t.Fatalf("incompatible live catalog was replaced or blamed on the key: %+v %v", models, err) + } +} + +func TestProviderKeySetupPersistsWithHonestFallback(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "fixture") + defer service.Close() + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &net.DNSError{Err: "offline"} + } + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "groq", Key: "fixture-key"}) + if err != nil || after.Discovery == nil || after.Discovery.Status != "unverified" { + t.Fatalf("setup = %+v %v", after, err) + } + cfg, err := config.Load() + if err != nil || cfg.Providers["groq"].APIKey != "fixture-key" { + t.Fatalf("saved key: %v", err) + } + if len(service.CatalogsFor(cfg)["groq"].Models) == 0 { + t.Fatal("saved key has no model choices") + } + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + return nil, &llm.HTTPError{Status: "401 Unauthorized", Body: "private"} + } + _, err = service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: after.Revision, Provider: "groq", Key: "rejected-key"}) + if err == nil || strings.Contains(err.Error(), "private") { + t.Fatalf("rejection: %v", err) + } + cfg, _ = config.Load() + if cfg.Providers["groq"].APIKey != "fixture-key" { + t.Fatal("rejected key replaced saved key") + } +} + +func TestProviderKeySetupSelectsAvailableEnvironmentAlias(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("DEEPINFRA_API_KEY", "") + t.Setenv("DEEPINFRA_TOKEN", "fixture-key") + service := NewProviderService(t.Context(), "fixture") + defer service.Close() + service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { + if endpoint != "https://api.deepinfra.com/v1/openai" || key != "fixture-key" { + t.Fatal("wrong environment key or destination") + } + return config.PresetModels("deepinfra"), nil + } + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + _, err = service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "deepinfra", Environment: true}) + if err != nil { + t.Fatal(err) + } + cfg, err := config.Load() + if err != nil || cfg.Providers["deepinfra"].APIKeyEnv != "DEEPINFRA_TOKEN" || cfg.Providers["deepinfra"].APIKey != "" { + t.Fatalf("saved environment reference: %+v %v", cfg.Providers["deepinfra"], err) + } +} + +func TestRefreshCatalogReplacesPriorMembershipWithEmptyLiveResponse(t *testing.T) { + for _, kind := range []string{"empty", "all incompatible"} { + t.Run(kind, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + cfg := config.Default() + provider := config.Provider{Name: "Cerebras", BaseURL: "https://api.cerebras.ai/v1", API: "openai-completions", APIKey: "fixture-key"} + cfg.Providers["cerebras"] = provider + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + prior := config.Catalog{FetchedAt: time.Now().Add(-time.Hour), BaseURL: provider.BaseURL, Models: []config.ModelInfoLite{{ID: "old-model"}}} + if err := config.UpdateCatalog("cerebras", prior); err != nil { + t.Fatal(err) + } + service := NewProviderService(t.Context(), "empty-live") + defer service.Close() + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { + if kind == "all incompatible" { + return []llm.ModelInfo{{ID: "non-chat-model", SupportsTools: new(false)}}, nil + } + return []llm.ModelInfo{}, nil + } + err := service.refreshCatalog(t.Context(), "cerebras", provider) + if !errors.Is(err, errNoCompatibleProviderModels) { + t.Fatalf("missing empty selection guidance: %v", err) + } + got, exists := config.LoadCatalogs()["cerebras"] + if !exists || len(got.Models) != 0 || !got.FetchedAt.After(prior.FetchedAt) { + t.Fatal("successful empty response retained prior/bundled membership") + } + if len(service.CatalogsFor(cfg)["cerebras"].Models) != 0 { + t.Fatal("metadata enrichment repopulated an empty catalog") + } + }) + } +} + +func TestSetProviderKeyDoesNotCacheModelsAfterNamedFileRotation(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("CEREBRAS_API_KEY", "") + filename := filepath.Join(t.TempDir(), "cerebras.key") + if err := os.WriteFile(filename, []byte("first-fixture"), 0o600); err != nil { + t.Fatal(err) + } + cfg := config.Default() + cfg.ProviderKeySources = config.ProviderKeySources{KeyFiles: map[string]string{"CEREBRAS_API_KEY": filename}} + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + service := NewProviderService(t.Context(), "rotate-key") + defer service.Close() + service.validate = func(_ context.Context, endpoint, key string) ([]llm.ModelInfo, error) { + if endpoint != "https://api.cerebras.ai/v1" || key != "first-fixture" { + t.Fatal("validation used wrong named key") + } + if err := os.WriteFile(filename, []byte("second-fixture"), 0o600); err != nil { + t.Fatal(err) + } + return []llm.ModelInfo{{ID: "old-key-only-model"}}, nil + } + before, err := service.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + connected, err := service.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "cerebras", Environment: true}) + if err != nil { + t.Fatal(err) + } + if connected.Discovery == nil || !strings.Contains(connected.Discovery.Message, "credentials changed") { + t.Fatal("rotated source lacked refresh guidance") + } + if _, exists := config.LoadCatalogs()["cerebras"]; exists { + t.Fatal("published catalog fetched with an obsolete credential") + } + saved, err := config.Load() + if err != nil { + t.Fatal(err) + } + if saved.Providers["cerebras"].APIKeyEnv != "CEREBRAS_API_KEY" || saved.Providers["cerebras"].APIKey != "" { + t.Fatal("lost named reference on rotation") + } + client, err := service.ModelClient(saved.Providers["cerebras"]) + if err != nil || client.APIKey != "second-fixture" { + t.Fatal("new client did not use rotated key") + } +} + +func TestModelClientUsesSuppliedConfigurationSnapshot(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("SNAPSHOT_FIXTURE_KEY", "") + directory := t.TempDir() + oldFile, newFile := filepath.Join(directory, "old.key"), filepath.Join(directory, "new.key") + if err := os.WriteFile(oldFile, []byte("old-route-fixture"), 0o600); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(newFile, []byte("new-route-fixture"), 0o600); err != nil { + t.Fatal(err) + } + oldCfg := config.Default() + oldCfg.ProviderKeySources.KeyFiles = map[string]string{"SNAPSHOT_FIXTURE_KEY": oldFile} + oldProvider := config.Provider{BaseURL: "https://old.example/v1", APIKeyEnv: "SNAPSHOT_FIXTURE_KEY"} + oldCfg.Providers["custom"] = oldProvider + newer := oldCfg.Snapshot() + newer.ProviderKeySources.KeyFiles["SNAPSHOT_FIXTURE_KEY"] = newFile + newer.Providers["custom"] = config.Provider{BaseURL: "https://new.example/v1", APIKeyEnv: "SNAPSHOT_FIXTURE_KEY"} + if err := newer.Save(); err != nil { + t.Fatal(err) + } + service := NewProviderService(t.Context(), "coherent-config") + defer service.Close() + client, err := service.ModelClient(oldProvider, oldCfg) + if err != nil || client.BaseURL != oldProvider.BaseURL || client.APIKey != "old-route-fixture" { + t.Fatal("old endpoint was combined with newer source configuration") + } + invoked := false + service.validate = func(context.Context, string, string) ([]llm.ModelInfo, error) { invoked = true; return nil, nil } + if err := service.refreshCatalog(t.Context(), "custom", oldProvider); err == nil || invoked { + t.Fatal("obsolete route reached provider HTTP before the preflight guard") + } +} diff --git a/internal/daemon/provider_openai.go b/internal/provider/provider_openai.go similarity index 86% rename from internal/daemon/provider_openai.go rename to internal/provider/provider_openai.go index 8f23adaef..f9d02c777 100644 --- a/internal/daemon/provider_openai.go +++ b/internal/provider/provider_openai.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" @@ -8,6 +8,7 @@ import ( "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/openaiauth" + "github.com/context-labs/whip/internal/protocol" ) func (s *ProviderService) loginOpenAI(flow *providerLoginFlow) { @@ -103,23 +104,23 @@ func (s *ProviderService) failOpenAILogin(flow *providerLoginFlow, err error) { flow.status.UserCode = "" } -func (s *ProviderService) openAIStatus() (ProviderStatus, error) { +func (s *ProviderService) openAIStatus() (protocol.ProviderStatus, error) { if s.openAIErr != nil { - return ProviderStatus{}, s.openAIErr + return protocol.ProviderStatus{}, s.openAIErr } cfg, err := config.Load() if err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } return s.openAIStatusFromConfig(cfg) } -func (s *ProviderService) openAIStatusFromConfig(cfg *config.Config) (ProviderStatus, error) { +func (s *ProviderService) openAIStatusFromConfig(cfg *config.Config) (protocol.ProviderStatus, error) { if s.openAIErr != nil { - return ProviderStatus{}, s.openAIErr + return protocol.ProviderStatus{}, s.openAIErr } entry, configured := cfg.Providers[openaiauth.Provider] - status := ProviderStatus{ + status := protocol.ProviderStatus{ Provider: openaiauth.Provider, Configured: configured, KeySource: "subscription", AuthMethod: "chatgpt", AuthState: "signed_out", Warnings: []string{}, } @@ -145,9 +146,9 @@ func (s *ProviderService) openAIStatusFromConfig(cfg *config.Config) (ProviderSt return status, nil } -func (s *ProviderService) logoutOpenAI(ctx context.Context) (ProviderStatus, error) { +func (s *ProviderService) logoutOpenAI(ctx context.Context) (protocol.ProviderStatus, error) { if s.openAIErr != nil { - return ProviderStatus{}, s.openAIErr + return protocol.ProviderStatus{}, s.openAIErr } s.mu.Lock() for _, flow := range s.flows { @@ -162,15 +163,15 @@ func (s *ProviderService) logoutOpenAI(ctx context.Context) (ProviderStatus, err return s.logoutOpenAILocked(ctx) } -func (s *ProviderService) logoutOpenAILocked(ctx context.Context) (ProviderStatus, error) { +func (s *ProviderService) logoutOpenAILocked(ctx context.Context) (protocol.ProviderStatus, error) { if err := ctx.Err(); err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } if err := s.openAI.Logout(); err != nil { - return ProviderStatus{}, err + return protocol.ProviderStatus{}, err } if err := config.DeleteCatalog(openaiauth.Provider); err != nil { - return ProviderStatus{}, errors.New("signed out of OpenAI, but the cached model catalog could not be removed") + return protocol.ProviderStatus{}, errors.New("signed out of OpenAI, but the cached model catalog could not be removed") } return s.openAIStatus() } diff --git a/internal/provider/provider_openai_test.go b/internal/provider/provider_openai_test.go new file mode 100644 index 000000000..966d42ac1 --- /dev/null +++ b/internal/provider/provider_openai_test.go @@ -0,0 +1,304 @@ +package provider + +import ( + "context" + "encoding/json" + "errors" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/openaiauth" +) + +func openAITestCredentials() openaiauth.Credentials { + return openaiauth.Credentials{ + AccessToken: "private-access-token", RefreshToken: "private-refresh-token", AccountID: "account-id", + ExpiresAt: time.Now().Add(time.Hour), Email: "account@example.com", Plan: "pro", + } +} + +func TestOpenAILoginFailureCanRetryAndCatalogFailureKeepsLogin(t *testing.T) { + for _, failure := range []string{"authorization", "credential storage"} { + t.Run(failure, func(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "retry") + t.Cleanup(service.Close) + attempts := 0 + service.openAILogin = func(_ context.Context, onCode func(string, string)) (openaiauth.Credentials, error) { + onCode("https://auth.openai.com/codex/device", "expired-code") + attempts++ + if attempts == 1 { + if failure == "authorization" { + return openaiauth.Credentials{}, errors.New("device authorization expired") + } + return openaiauth.Credentials{}, nil + } + return openAITestCredentials(), nil + } + service.refreshModels = func(context.Context, string, config.Provider) error { + return errors.New("upstream failed with private-access-token") + } + first, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + failed := waitProviderState(t, service, first.FlowID, "failed") + if failed.Error == "" || failed.UserCode != "" { + t.Fatalf("failed authorization retained a code or lost its error: %+v", failed) + } + status, err := service.ProviderStatus(openaiauth.Provider) + if err != nil || status.AuthState != "signed_out" { + t.Fatalf("failed login became connected: %+v %v", status, err) + } + retry, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil || retry.FlowID == first.FlowID { + t.Fatalf("failed flow cannot be retried: %+v %v", retry, err) + } + completed := waitProviderState(t, service, retry.FlowID, "succeeded") + if completed.UserCode != "" || !strings.Contains(completed.Error, "Model discovery failed") || strings.Contains(completed.Error, "private-") { + t.Fatalf("discovery failure did not preserve a safe completed login: %+v", completed) + } + status, err = service.ProviderStatus(openaiauth.Provider) + if err != nil || status.AuthState != "connected" || status.Available == nil || !*status.Available { + t.Fatalf("catalog failure invalidated saved login: %+v %v", status, err) + } + }) + } +} + +func TestOpenAICancelledLogoutPreservesCredentials(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "cancelled-logout") + t.Cleanup(service.Close) + if err := service.openAI.Install(t.Context(), service.openAI.Generation(), openAITestCredentials()); err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithCancel(t.Context()) + cancel() + if _, err := service.LogoutProvider(ctx, openaiauth.Provider); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled logout: %v", err) + } + credentials, err := service.openAI.Snapshot() + if err != nil || credentials.AccessToken != openAITestCredentials().AccessToken { + t.Fatalf("cancelled logout discarded credentials: %v", err) + } +} + +func TestOpenAILoginPreservesConcurrentConfigurationConflict(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "conflict") + t.Cleanup(service.Close) + service.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers[openaiauth.Provider] = config.Provider{API: "openai-completions", BaseURL: "https://custom.example/v1"} + return nil + }) + return openAITestCredentials(), err + } + service.refreshModels = func(context.Context, string, config.Provider) error { + t.Error("discovery ran for a conflicting route") + return errors.New("discovery must not run for a conflicting route") + } + flow, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + failed := waitProviderState(t, service, flow.FlowID, "failed") + if !strings.Contains(failed.Error, "configuration could not be saved") || failed.UserCode != "" { + t.Fatalf("partial setup needs recovery guidance: %+v", failed) + } + status, err := service.ProviderStatus(openaiauth.Provider) + if err != nil || status.AuthState != "configuration_error" || status.Available == nil || *status.Available { + t.Fatalf("conflicting setup reported ready: %+v %v", status, err) + } + configuration, err := config.Load() + if err != nil || configuration.Providers[openaiauth.Provider].BaseURL != "https://custom.example/v1" { + t.Fatalf("sign-in overwrote the concurrent route edit: %v", err) + } + credentials, err := service.openAI.Snapshot() + if err != nil || credentials.AccessToken != openAITestCredentials().AccessToken { + t.Fatalf("partial setup lost completed authorization: %v", err) + } +} + +func TestOpenAILoginRecoveryPersistenceAndLogout(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "first") + service.refreshModels = func(context.Context, string, config.Provider) error { return nil } + t.Cleanup(service.Close) + ready, release := make(chan struct{}), make(chan struct{}) + service.openAILogin = func(ctx context.Context, onCode func(string, string)) (openaiauth.Credentials, error) { + onCode("https://auth.openai.com/codex/device", "public-code") + close(ready) + select { + case <-ctx.Done(): + return openaiauth.Credentials{}, ctx.Err() + case <-release: + return openAITestCredentials(), nil + } + } + first, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + <-ready + second, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil || first.FlowID != second.FlowID || second.UserCode != "public-code" { + t.Fatalf("duplicate login was not recovered: %v", err) + } + if flows := service.ListLogins(); len(flows.Flows) != 1 || flows.Flows[0].Provider != openaiauth.Provider { + t.Fatal("lost acknowledgement cannot be recovered") + } + close(release) + completed := waitProviderState(t, service, first.FlowID, "succeeded") + status, err := service.ProviderStatus(openaiauth.Provider) + if err != nil || !status.Configured || status.AuthState != "connected" || status.Email != "account@example.com" { + t.Fatalf("incorrect connected status: %+v %v", status, err) + } + for _, value := range []any{completed, status, service.ListLogins()} { + data, err := json.Marshal(value) + if err != nil || strings.Contains(string(data), "private-") { + t.Fatal("credentials reached a public response") + } + } + service.Close() + restarted := NewProviderService(t.Context(), "second") + t.Cleanup(restarted.Close) + credentials, err := restarted.openAI.Credentials(t.Context()) + if err != nil || credentials.AccessToken != "private-access-token" { + t.Fatalf("saved login did not survive restart: %v", err) + } + if old, err := restarted.LoginStatus(first.FlowID); err != nil || old.State != "interrupted" { + t.Fatalf("old flow did not report interruption: %v", err) + } + status, err = restarted.LogoutProvider(t.Context(), openaiauth.Provider) + if err != nil || status.AuthState != "signed_out" || !status.Configured { + t.Fatalf("logout changed route or retained login: %+v %v", status, err) + } + if _, err := restarted.openAI.Credentials(t.Context()); !errors.Is(err, openaiauth.ErrSignInRequired) { + t.Fatalf("credentials survived logout: %v", err) + } +} + +func TestOpenAISetupRetryUsesSavedLogin(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "generation") + service.refreshModels = func(context.Context, string, config.Provider) error { return nil } + t.Cleanup(service.Close) + if err := service.openAI.Install(t.Context(), service.openAI.Generation(), openAITestCredentials()); err != nil { + t.Fatal(err) + } + service.openAILogin = func(context.Context, func(string, string)) (openaiauth.Credentials, error) { + t.Error("requested new OAuth authorization for an already saved login") + return openaiauth.Credentials{}, errors.New("unexpected login") + } + status, err := service.ProviderStatus(openaiauth.Provider) + if err != nil || status.AuthState != "setup_required" { + t.Fatalf("partial setup was reported ready: %+v %v", status, err) + } + flow, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + waitProviderState(t, service, flow.FlowID, "succeeded") +} + +func TestOpenAILogoutCancelsOnlyOwnFlows(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "generation") + t.Cleanup(service.Close) + service.openAILogin = func(ctx context.Context, _ func(string, string)) (openaiauth.Credentials, error) { + <-ctx.Done() + return openaiauth.Credentials{}, ctx.Err() + } + service.login = func(ctx context.Context, _ func(string, string)) (providerLoginIdentity, error) { + <-ctx.Done() + return providerLoginIdentity{teams: []inferencenet.Team{}}, ctx.Err() + } + openAI, err := service.BeginProviderLogin(openaiauth.Provider) + if err != nil { + t.Fatal(err) + } + inference, err := service.BeginLogin() + if err != nil { + t.Fatal(err) + } + if _, err := service.LogoutProvider(t.Context(), openaiauth.Provider); err != nil { + t.Fatal(err) + } + waitProviderState(t, service, openAI.FlowID, "interrupted") + status, err := service.LoginStatus(inference.FlowID) + if err != nil || status.State != "authorizing" { + t.Fatalf("cancelled unrelated provider: %v", err) + } +} + +func TestOpenAIRejectsConflictingProfileBeforeLogin(t *testing.T) { + directory := t.TempDir() + t.Setenv("WHIPCODE_HOME", directory) + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.Providers[openaiauth.Provider] = config.Provider{API: "openai-completions", BaseURL: "https://example.com"} + return nil + }) + if err != nil { + t.Fatal(err) + } + before, err := os.ReadFile(filepath.Join(directory, "config.json")) + if err != nil { + t.Fatal(err) + } + service := NewProviderService(t.Context(), "generation") + t.Cleanup(service.Close) + if _, err := service.BeginProviderLogin(openaiauth.Provider); err == nil { + t.Fatal("accepted conflicting route") + } + after, err := os.ReadFile(filepath.Join(directory, "config.json")) + if err != nil || string(before) != string(after) { + t.Fatal("changed existing configuration") + } +} + +func TestOpenAICatalogIsScopedToConnectedAccount(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + service := NewProviderService(t.Context(), "catalog") + t.Cleanup(service.Close) + credentials := openAITestCredentials() + if err := service.openAI.Install(t.Context(), service.openAI.Generation(), credentials); err != nil { + t.Fatal(err) + } + cfg := config.Default() + if err := cfg.UpsertOpenAICodex(); err != nil { + t.Fatal(err) + } + cfg.Providers["api"] = config.Provider{BaseURL: "https://example.com", APIKey: "api-fixture-key"} + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + if err := config.SaveCatalogs(map[string]config.Catalog{ + openaiauth.Provider: {BaseURL: openaiauth.BaseURL, AccountID: credentials.AccountID}, + "api": {BaseURL: "https://example.com"}, + }); err != nil { + t.Fatal(err) + } + if len(service.Catalogs()) != 2 { + t.Fatal("connected account's catalog disappeared") + } + credentials.AccountID = "replacement-account" + if err := service.openAI.Install(t.Context(), service.openAI.Generation(), credentials); err != nil { + t.Fatal(err) + } + if catalogs := service.Catalogs(); len(catalogs) != 1 || catalogs["api"].BaseURL == "" { + t.Fatal("replacement account could see the previous subscription catalog") + } + if _, err := service.LogoutProvider(t.Context(), openaiauth.Provider); err != nil { + t.Fatal(err) + } + if _, exists := config.LoadCatalogs()[openaiauth.Provider]; exists { + t.Fatal("logout retained the subscription catalog on disk") + } +} diff --git a/internal/daemon/provider_selection.go b/internal/provider/provider_selection.go similarity index 97% rename from internal/daemon/provider_selection.go rename to internal/provider/provider_selection.go index bfbb82b3d..cef0dffa4 100644 --- a/internal/daemon/provider_selection.go +++ b/internal/provider/provider_selection.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "cmp" @@ -11,7 +11,7 @@ import ( "github.com/context-labs/whip/internal/protocol" ) -func providerCanAttempt(status ProviderStatus) bool { +func providerCanAttempt(status protocol.ProviderStatus) bool { return !status.Disabled && ((status.Available != nil && *status.Available) || status.AuthState == "unchecked") } diff --git a/internal/provider/provider_selection_test.go b/internal/provider/provider_selection_test.go new file mode 100644 index 000000000..763ea2538 --- /dev/null +++ b/internal/provider/provider_selection_test.go @@ -0,0 +1,247 @@ +package provider + +import ( + "context" + "errors" + "os" + "path/filepath" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/protocol" +) + +func TestProviderSelectionPreservesRoutesAndRecommendsOnlyAvailableModels(t *testing.T) { + for _, test := range []struct { + name string + inference, router bool + model, provider string + ready bool + wantProvider string + }{ + {name: "clean", wantProvider: "inference-net"}, + {name: "inference detected", inference: true, ready: true, wantProvider: "inference-net"}, + {name: "router detected leaves default explicit", router: true, wantProvider: "inference-net"}, + {name: "explicit router", inference: true, router: true, model: "moonshotai/kimi-k2.5", provider: "openrouter", ready: true, wantProvider: "openrouter"}, + {name: "unknown explicit model", inference: true, model: "unknown", provider: "inference-net", wantProvider: "inference-net"}, + } { + t.Run(test.name, func(t *testing.T) { + s := providerConnectionsFixture(t) + if test.inference { + t.Setenv(config.InferenceNetEnvVar, "fixture") + } + if test.router { + t.Setenv(config.OpenRouterEnvVar, "fixture") + } + if _, err := config.Load(); err != nil { + t.Fatal(err) + } + if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, FetchedAt: time.Now(), Models: []config.ModelInfoLite{{ID: "alphabetically-first"}, {ID: "moonshotai/kimi-k2.5"}}}); err != nil { + t.Fatal(err) + } + list, err := s.ListProvidersFor(test.model, test.provider) + if err != nil { + t.Fatal(err) + } + if list.Selection == nil || list.Selection.Ready != test.ready || list.Selection.Provider != test.wantProvider { + t.Fatalf("selection = %+v", list.Selection) + } + if list.Providers[0].ID != config.InferenceNetProvider || !list.Providers[0].Recommended { + t.Fatal("missing restrained Inference.net preference") + } + if test.router && providerEntry(t, s, "openrouter").SuggestedModel != "moonshotai/kimi-k2.5" { + t.Fatal("did not recommend an available coding candidate") + } + cfg, err := config.Load() + if err != nil || cfg.DefaultModel != "kimi-k3-fast" || cfg.DefaultProvider != "" { + t.Fatal("inventory changed defaults") + } + }) + } +} + +func TestProviderSelectionMatchesCatalogRoutePrecedence(t *testing.T) { + for _, test := range []struct { + name, explicit string + shared bool + want string + }{ + {name: "catalog route precedes host default", want: "catalog-provider"}, + {name: "host default does not resolve ambiguity", shared: true}, + {name: "explicit route resolves ambiguity", shared: true, explicit: "default-provider", want: "default-provider"}, + } { + t.Run(test.name, func(t *testing.T) { + s := providerConnectionsFixture(t) + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.DefaultProvider = "default-provider" + for _, name := range []string{"default-provider", "catalog-provider"} { + cfg.Providers[name] = config.Provider{BaseURL: "https://" + name + ".test/v1", APIKey: "fixture"} + } + return nil + }) + if err != nil { + t.Fatal(err) + } + for _, name := range []string{"default-provider", "catalog-provider"} { + catalog := config.Catalog{BaseURL: "https://" + name + ".test/v1"} + if name == "catalog-provider" || test.shared { + catalog.Models = []config.ModelInfoLite{{ID: "catalog-only-model"}} + } + if err := config.UpdateCatalog(name, catalog); err != nil { + t.Fatal(err) + } + } + cfg, err := config.Load() + if err != nil { + t.Fatal(err) + } + route, _, _, _, routeErr := cfg.ResolveRoute("catalog-only-model", test.explicit) + list, err := s.ListProvidersFor("catalog-only-model", test.explicit) + if err != nil { + t.Fatal(err) + } + selection := list.Selection + if route != test.want || (routeErr == nil) != (test.want != "") || selection.Ready != (routeErr == nil) || selection.Provider != route { + t.Fatalf("runtime route=%q err=%v, readiness=%+v, want route=%q", route, routeErr, selection, test.want) + } + }) + } +} + +func TestProviderSelectionRespectsDisabledCustomAndCredentialCommands(t *testing.T) { + s := providerConnectionsFixture(t) + marker := filepath.Join(t.TempDir(), "secret-command-executed") + _, _, err := config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.DefaultProvider, cfg.DefaultModel = "custom", "coding" + cfg.Providers["custom"] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "!touch " + marker} + cfg.Models["coding"] = config.Model{Providers: []string{"custom"}} + cfg.DisabledProviders = []string{"inference-net"} + return nil + }) + if err != nil { + t.Fatal(err) + } + list, err := s.ListProviders() + if err != nil || !list.Selection.Ready || list.Selection.Provider != "custom" { + t.Fatalf("selection = %+v, %v", list.Selection, err) + } + if list.Providers[0].Recommended { + t.Fatal("promoted a disabled provider") + } + if _, err := os.Stat(marker); !errors.Is(err, os.ErrNotExist) { + t.Fatal("executed a credential command during discovery") + } + _, _, err = config.UpdateVersioned("", func(cfg *config.Config) error { + cfg.DisabledProviders = nil + cfg.Providers["inference-net"] = config.Provider{BaseURL: "https://custom.test/v1", APIKey: "fixture"} + return nil + }) + if err != nil { + t.Fatal(err) + } + if providerEntry(t, s, "inference-net").Recommended { + t.Fatal("promoted a custom endpoint as Inference.net") + } +} + +func TestProviderDefaultPairValidationAndPersistence(t *testing.T) { + s := providerConnectionsFixture(t) + t.Setenv(config.OpenRouterEnvVar, "fixture") + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + if err := config.UpdateCatalog("openrouter", config.Catalog{BaseURL: config.OpenRouterBaseURL, Models: []config.ModelInfoLite{{ID: "moonshotai/kimi-k2.5", ReasoningEfforts: []string{"low"}}}}); err != nil { + t.Fatal(err) + } + model, provider := "moonshotai/kimi-k2.5", "openrouter" + _, err = s.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DefaultModel: new("not-advertised"), DefaultProvider: &provider}) + if err == nil { + t.Fatal("accepted an unavailable model") + } + updated, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DefaultModel: &model, DefaultProvider: &provider, DefaultEffort: new("")}) + if err != nil { + t.Fatal(err) + } + if _, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DefaultModel: &model, DefaultProvider: &provider}); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatalf("stale update = %v", err) + } + restarted := NewProviderService(t.Context(), "restarted") + t.Cleanup(restarted.Close) + list, err := restarted.ListProviders() + if err != nil || !list.Selection.Ready || list.Selection.Model != model || list.Selection.Provider != provider || list.Revision != updated.Revision { + t.Fatalf("restarted selection = %+v, %v", list.Selection, err) + } +} + +func TestProviderLoginSkipsOnlySingletonChoices(t *testing.T) { + s := providerConnectionsFixture(t) + s.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { + return providerLoginIdentity{token: "fixture-secret", teams: []inferencenet.Team{{ID: "team", Name: "Only workspace"}}}, nil + } + s.projects = func(context.Context, string, inferencenet.Team) ([]inferencenet.Project, error) { + return []inferencenet.Project{{ID: "project", Name: "Only project"}}, nil + } + finished := make(chan inferencenet.Auth, 1) + s.finish = func(_ context.Context, auth inferencenet.Auth) error { finished <- auth; return nil } + s.create = func(context.Context, string, inferencenet.Team, string) (inferencenet.Project, error) { + t.Error("automatically created a project") + return inferencenet.Project{}, errors.New("unexpected create") + } + flow, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + status := waitProviderState(t, s, flow.FlowID, "succeeded") + if status.TeamID != "team" || status.ProjectID != "project" { + t.Fatalf("lost selected context: %+v", status) + } + if auth := <-finished; auth.ProjectID != "project" || auth.TeamID != "team" { + t.Fatalf("wrong provisioned context: %+v", auth) + } + if _, err := s.SelectLoginProject(flow.FlowID, "project"); err == nil { + t.Fatal("duplicate provisioning allowed") + } +} + +func TestConcurrentInferenceLoginReusesActiveFlow(t *testing.T) { + s := providerConnectionsFixture(t) + var calls atomic.Int32 + s.login = func(ctx context.Context, _ func(string, string)) (providerLoginIdentity, error) { + calls.Add(1) + <-ctx.Done() + return providerLoginIdentity{}, ctx.Err() + } + var wg sync.WaitGroup + ids := make(chan string, 8) + for range 8 { + wg.Go(func() { + flow, err := s.BeginLogin() + if err != nil { + t.Error(err) + return + } + ids <- flow.FlowID + }) + } + wg.Wait() + close(ids) + var first string + for id := range ids { + if first != "" && id != first { + t.Fatalf("concurrent login created different flows: %q and %q", first, id) + } + first = id + } + if first == "" { + t.Fatal("no login flow returned") + } + s.Close() + if calls.Load() != 1 { + t.Fatalf("started %d login attempts", calls.Load()) + } +} diff --git a/internal/daemon/provider_service.go b/internal/provider/provider_service.go similarity index 82% rename from internal/daemon/provider_service.go rename to internal/provider/provider_service.go index 99294bdff..3869fbbdf 100644 --- a/internal/daemon/provider_service.go +++ b/internal/provider/provider_service.go @@ -1,4 +1,4 @@ -package daemon +package provider import ( "context" @@ -19,21 +19,8 @@ import ( "github.com/context-labs/whip/internal/session" ) -// RuntimeConfiguration contains settings safe to send to clients. Credentials -// and integration definitions stay on the execution host. -type RuntimeConfiguration = protocol.RuntimeConfiguration - -type ConfigurationUpdate = protocol.ConfigurationUpdate - -// ProviderKeySetup is ephemeral: never write it to a command journal or log. -type ProviderKeySetup = protocol.ProviderKeySetup - -type ProviderChoice = protocol.ProviderChoice - -type ProviderLoginStatus = protocol.ProviderLoginStatus - type providerLoginFlow struct { - status ProviderLoginStatus + status protocol.ProviderLoginStatus ctx context.Context cancel context.CancelFunc token string @@ -151,7 +138,7 @@ func (s *ProviderService) Close() { } } -func runtimeConfiguration(c *config.Config, revision string) RuntimeConfiguration { +func runtimeConfiguration(c *config.Config, revision string) protocol.RuntimeConfiguration { hosts := append([]config.RemoteHost{}, c.RemoteHosts...) claude, codex := true, true if c.MCPImport != nil { @@ -163,7 +150,7 @@ func runtimeConfiguration(c *config.Config, revision string) RuntimeConfiguratio } } disabled := append([]string{}, c.DisabledProviders...) - return RuntimeConfiguration{ + return protocol.RuntimeConfiguration{ DisabledProviders: &disabled, DefaultExecutionEngine: c.RLM.Engine(), DefaultPermissionMode: session.DefaultPermissionMode(c.DefaultPermissionMode), @@ -177,17 +164,17 @@ func runtimeConfiguration(c *config.Config, revision string) RuntimeConfiguratio } } -func (s *ProviderService) ReadConfiguration() (RuntimeConfiguration, error) { +func (s *ProviderService) ReadConfiguration() (protocol.RuntimeConfiguration, error) { c, revision, err := config.ReadVersioned() if err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } return runtimeConfiguration(c, revision), nil } -func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeConfiguration, error) { +func (s *ProviderService) UpdateConfiguration(p protocol.ConfigurationUpdate) (protocol.RuntimeConfiguration, error) { if p.Revision == "" { - return RuntimeConfiguration{}, errors.New("configuration revision is required") + return protocol.RuntimeConfiguration{}, errors.New("configuration revision is required") } if p.DisabledProviders != nil { s.provisionMu.Lock() @@ -312,7 +299,7 @@ func (s *ProviderService) UpdateConfiguration(p ConfigurationUpdate) (RuntimeCon return nil }) if err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } if p.DisabledProviders != nil { for _, name := range c.DisabledProviders { @@ -341,18 +328,18 @@ func (s *ProviderService) ConfigureCompaction(c *config.Config, model, provider return nil } -func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup) (RuntimeConfiguration, error) { +func (s *ProviderService) SetProviderKey(ctx context.Context, p protocol.ProviderKeySetup) (protocol.RuntimeConfiguration, error) { if p.Revision == "" { - return RuntimeConfiguration{}, errors.New("configuration revision is required") + return protocol.RuntimeConfiguration{}, errors.New("configuration revision is required") } s.provisionMu.Lock() defer s.provisionMu.Unlock() c, revision, err := config.ReadVersioned() if err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } if revision != p.Revision { - return RuntimeConfiguration{}, config.ErrRevisionConflict + return protocol.RuntimeConfiguration{}, config.ErrRevisionConflict } provider, ok := c.Providers[p.Provider] for _, preset := range config.ProviderPresets() { @@ -367,7 +354,7 @@ func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup } } if !ok || (provider.API != "" && !config.KnownAPI(provider.API)) { - return RuntimeConfiguration{}, errors.New("provider does not support API key setup") + return protocol.RuntimeConfiguration{}, errors.New("provider does not support API key setup") } credential := protocol.ProviderCredential{Mode: "api_key", Key: p.Key} if p.Environment { @@ -375,29 +362,29 @@ func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup } provider, err = applyProviderCredential(provider, credential, false) if err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } if provider.Name == "" { provider.Name = p.Provider } if err := validateProviderDefinition(provider); err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } key, err := provider.ResolveKey(c) if err != nil || key == "" { - return RuntimeConfiguration{}, errors.New("provider key is unavailable on the execution host") + return protocol.RuntimeConfiguration{}, errors.New("provider key is unavailable on the execution host") } validationCtx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() models, discovery, err := s.discoverProviderModels(validationCtx, p.Provider, provider, key) if err != nil { if ctx.Err() != nil { - return RuntimeConfiguration{}, ctx.Err() + return protocol.RuntimeConfiguration{}, ctx.Err() } - return RuntimeConfiguration{}, providerValidationError(err) + return protocol.RuntimeConfiguration{}, providerValidationError(err) } if err := ctx.Err(); err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } c, revision, err = config.UpdateVersioned(p.Revision, func(c *config.Config) error { if err := ctx.Err(); err != nil { @@ -406,7 +393,7 @@ func (s *ProviderService) SetProviderKey(ctx context.Context, p ProviderKeySetup return patchProviderConfiguration(c, p.Provider, provider, nil, false, true) }) if err != nil { - return RuntimeConfiguration{}, err + return protocol.RuntimeConfiguration{}, err } s.interruptProviderLogins(p.Provider) // Named files can rotate without changing the configuration revision. @@ -431,49 +418,49 @@ func loginActive(state string) bool { return state == "authorizing" || state == "choose_team" || state == "loading_projects" || state == "choose_project" || state == "provisioning" } -func loginSnapshot(flow *providerLoginFlow) ProviderLoginStatus { +func loginSnapshot(flow *providerLoginFlow) protocol.ProviderLoginStatus { status := flow.status - status.Teams = append([]ProviderChoice{}, status.Teams...) - status.Projects = append([]ProviderChoice{}, status.Projects...) + status.Teams = append([]protocol.ProviderChoice{}, status.Teams...) + status.Projects = append([]protocol.ProviderChoice{}, status.Projects...) return status } -func (s *ProviderService) BeginLogin() (ProviderLoginStatus, error) { +func (s *ProviderService) BeginLogin() (protocol.ProviderLoginStatus, error) { return s.BeginProviderLogin(config.InferenceNetProvider) } -func (s *ProviderService) BeginProviderLogin(provider string) (ProviderLoginStatus, error) { +func (s *ProviderService) BeginProviderLogin(provider string) (protocol.ProviderLoginStatus, error) { if provider == "" { provider = config.InferenceNetProvider } if provider != config.InferenceNetProvider && provider != openaiauth.Provider { - return ProviderLoginStatus{}, errors.New("provider does not support account login") + return protocol.ProviderLoginStatus{}, errors.New("provider does not support account login") } if provider == config.InferenceNetProvider { cfg, err := config.Load() if err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } if err := inferenceNetLoginRoute(cfg); err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } } if provider == openaiauth.Provider { if s.openAIErr != nil { - return ProviderLoginStatus{}, s.openAIErr + return protocol.ProviderLoginStatus{}, s.openAIErr } cfg, err := config.Load() if err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } if err := cfg.UpsertOpenAICodex(); err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } } s.mu.Lock() defer s.mu.Unlock() if err := s.ctx.Err(); err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } active := 0 for id, flow := range s.flows { @@ -487,11 +474,11 @@ func (s *ProviderService) BeginProviderLogin(provider string) (ProviderLoginStat } } if active >= 16 || len(s.flows) >= 64 { - return ProviderLoginStatus{}, errors.New("provider login limit reached") + return protocol.ProviderLoginStatus{}, errors.New("provider login limit reached") } var random [16]byte if _, err := rand.Read(random[:]); err != nil { - return ProviderLoginStatus{}, err + return protocol.ProviderLoginStatus{}, err } id := s.generation + ":" + hex.EncodeToString(random[:]) lifetime := s.lifetime @@ -499,8 +486,8 @@ func (s *ProviderService) BeginProviderLogin(provider string) (ProviderLoginStat lifetime = openaiauth.DeviceLifetime } ctx, cancel := context.WithTimeout(s.ctx, lifetime) - flow := &providerLoginFlow{ctx: ctx, cancel: cancel, status: ProviderLoginStatus{ - FlowID: id, Provider: provider, State: "authorizing", Teams: []ProviderChoice{}, Projects: []ProviderChoice{}, + flow := &providerLoginFlow{ctx: ctx, cancel: cancel, status: protocol.ProviderLoginStatus{ + FlowID: id, Provider: provider, State: "authorizing", Teams: []protocol.ProviderChoice{}, Projects: []protocol.ProviderChoice{}, ExpiresAt: time.Now().Add(lifetime), }} s.flows[id] = flow @@ -543,7 +530,7 @@ func (s *ProviderService) BeginProviderLogin(provider string) (ProviderLoginStat } flow.token, flow.teams, flow.status.Email = identity.token, identity.teams, identity.email for _, team := range identity.teams { - flow.status.Teams = append(flow.status.Teams, ProviderChoice{ID: team.ID, Name: team.Name}) + flow.status.Teams = append(flow.status.Teams, protocol.ProviderChoice{ID: team.ID, Name: team.Name}) } flow.status.State = "choose_team" if len(flow.teams) == 1 && flow.teams[0].ID != "" { @@ -553,25 +540,25 @@ func (s *ProviderService) BeginProviderLogin(provider string) (ProviderLoginStat return loginSnapshot(flow), nil } -func (s *ProviderService) LoginStatus(id string) (ProviderLoginStatus, error) { +func (s *ProviderService) LoginStatus(id string) (protocol.ProviderLoginStatus, error) { s.mu.Lock() defer s.mu.Unlock() flow := s.flows[id] if flow == nil { if id != "" && !strings.HasPrefix(id, s.generation+":") { - return ProviderLoginStatus{FlowID: id, State: "interrupted", Teams: []ProviderChoice{}, Projects: []ProviderChoice{}}, nil + return protocol.ProviderLoginStatus{FlowID: id, State: "interrupted", Teams: []protocol.ProviderChoice{}, Projects: []protocol.ProviderChoice{}}, nil } - return ProviderLoginStatus{}, errors.New("provider login is unavailable; start a new login") + return protocol.ProviderLoginStatus{}, errors.New("provider login is unavailable; start a new login") } return loginSnapshot(flow), nil } -func (s *ProviderService) CancelLogin(id string) (ProviderLoginStatus, error) { +func (s *ProviderService) CancelLogin(id string) (protocol.ProviderLoginStatus, error) { s.mu.Lock() defer s.mu.Unlock() flow := s.flows[id] if flow == nil { - return ProviderLoginStatus{}, errors.New("unknown provider login") + return protocol.ProviderLoginStatus{}, errors.New("unknown provider login") } if loginActive(flow.status.State) { if flow.status.State == "provisioning" { @@ -590,16 +577,16 @@ func (s *ProviderService) failLogin(flow *providerLoginFlow) { flow.cancel() } -func (s *ProviderService) SelectLoginTeam(id, teamID string) (ProviderLoginStatus, error) { +func (s *ProviderService) SelectLoginTeam(id, teamID string) (protocol.ProviderLoginStatus, error) { s.mu.Lock() defer s.mu.Unlock() flow := s.flows[id] if flow == nil || (flow.status.State != "choose_team" && flow.status.State != "choose_project") || flow.ctx.Err() != nil { - return ProviderLoginStatus{}, errors.New("login is not waiting for a team") + return protocol.ProviderLoginStatus{}, errors.New("login is not waiting for a team") } index := slices.IndexFunc(flow.teams, func(team inferencenet.Team) bool { return team.ID == teamID }) if index < 0 { - return ProviderLoginStatus{}, errors.New("unknown login team") + return protocol.ProviderLoginStatus{}, errors.New("unknown login team") } s.selectLoginTeam(flow, flow.teams[index]) return loginSnapshot(flow), nil @@ -608,7 +595,7 @@ func (s *ProviderService) SelectLoginTeam(id, teamID string) (ProviderLoginStatu // selectLoginTeam starts discovery while the caller holds s.mu. func (s *ProviderService) selectLoginTeam(flow *providerLoginFlow, selected inferencenet.Team) { flow.team, flow.status.TeamID, flow.status.State = selected, selected.ID, "loading_projects" - flow.projects, flow.status.Projects = nil, []ProviderChoice{} + flow.projects, flow.status.Projects = nil, []protocol.ProviderChoice{} flow.status.ProjectID = "" token, team := flow.token, flow.team s.wg.Go(func() { @@ -624,7 +611,7 @@ func (s *ProviderService) selectLoginTeam(flow *providerLoginFlow, selected infe } flow.projects = projects for _, project := range projects { - flow.status.Projects = append(flow.status.Projects, ProviderChoice{ID: project.ID, Name: project.Name}) + flow.status.Projects = append(flow.status.Projects, protocol.ProviderChoice{ID: project.ID, Name: project.Name}) } flow.status.State = "choose_project" if len(projects) == 1 && projects[0].ID != "" { @@ -633,30 +620,30 @@ func (s *ProviderService) selectLoginTeam(flow *providerLoginFlow, selected infe }) } -func (s *ProviderService) SelectLoginProject(id, projectID string) (ProviderLoginStatus, error) { +func (s *ProviderService) SelectLoginProject(id, projectID string) (protocol.ProviderLoginStatus, error) { return s.completeLogin(id, projectID, "") } -func (s *ProviderService) CreateLoginProject(id, name string) (ProviderLoginStatus, error) { +func (s *ProviderService) CreateLoginProject(id, name string) (protocol.ProviderLoginStatus, error) { name = strings.TrimSpace(name) if name == "" || len(name) > 256 { - return ProviderLoginStatus{}, errors.New("project name must contain 1 to 256 bytes") + return protocol.ProviderLoginStatus{}, errors.New("project name must contain 1 to 256 bytes") } return s.completeLogin(id, "", name) } -func (s *ProviderService) completeLogin(id, projectID, name string) (ProviderLoginStatus, error) { +func (s *ProviderService) completeLogin(id, projectID, name string) (protocol.ProviderLoginStatus, error) { s.mu.Lock() defer s.mu.Unlock() flow := s.flows[id] if flow == nil || flow.status.State != "choose_project" || flow.ctx.Err() != nil { - return ProviderLoginStatus{}, errors.New("login is not waiting for a project") + return protocol.ProviderLoginStatus{}, errors.New("login is not waiting for a project") } var project inferencenet.Project if name == "" { index := slices.IndexFunc(flow.projects, func(project inferencenet.Project) bool { return project.ID == projectID }) if index < 0 { - return ProviderLoginStatus{}, errors.New("unknown login project") + return protocol.ProviderLoginStatus{}, errors.New("unknown login project") } project = flow.projects[index] } diff --git a/internal/provider/provider_service_test.go b/internal/provider/provider_service_test.go new file mode 100644 index 000000000..30bdeb6ba --- /dev/null +++ b/internal/provider/provider_service_test.go @@ -0,0 +1,441 @@ +package provider + +import ( + "context" + "encoding/json" + "errors" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" +) + +func waitProviderState(t *testing.T, service *ProviderService, id, state string) protocol.ProviderLoginStatus { + t.Helper() + deadline := time.Now().Add(2 * time.Second) + for time.Now().Before(deadline) { + result, err := service.LoginStatus(id) + if err != nil { + t.Fatal(err) + } + if result.State == state { + return result + } + time.Sleep(time.Millisecond) + } + result, _ := service.LoginStatus(id) + t.Fatalf("wanted %s, got %s", state, result.State) + return protocol.ProviderLoginStatus{} +} + +func TestProviderLoginReconnectChoicesAndSecretIsolation(t *testing.T) { + s := NewProviderService(t.Context(), "generation-a") + defer s.Close() + s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { + code("https://example.com/verify", "public-code") + return providerLoginIdentity{token: "secret-session-token", email: "person@example.com", teams: []inferencenet.Team{{ID: "team", Name: "Team"}, {ID: "other", Name: "Other"}}}, nil + } + s.projects = func(ctx context.Context, token string, team inferencenet.Team) ([]inferencenet.Project, error) { + if token != "secret-session-token" || team.ID != "team" { + return nil, errors.New("bad selection") + } + return []inferencenet.Project{{ID: "project", Name: "Project"}, {ID: "other", Name: "Other"}}, nil + } + finished := make(chan inferencenet.Auth, 1) + s.finish = func(ctx context.Context, auth inferencenet.Auth) error { finished <- auth; return nil } + started, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + status := waitProviderState(t, s, started.FlowID, "choose_team") + if status.VerificationURL == "" || len(status.Teams) != 2 { + t.Fatal("missing reconnect choices") + } + status.Teams[0].ID = "mutated" + if _, err := s.SelectLoginTeam(started.FlowID, "invalid"); err == nil { + t.Fatal("accepted unknown team") + } + if _, err := s.SelectLoginTeam(started.FlowID, "team"); err != nil { + t.Fatal(err) + } + waitProviderState(t, s, started.FlowID, "choose_project") + if _, err := s.SelectLoginProject(started.FlowID, "project"); err != nil { + t.Fatal(err) + } + status = waitProviderState(t, s, started.FlowID, "succeeded") + auth := <-finished + if auth.SessionToken != "secret-session-token" || auth.ProjectID != "project" || auth.TeamName != "Team" { + t.Fatal("missing host-side auth") + } + encoded, err := json.Marshal(status) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(encoded), "secret") || strings.Contains(string(encoded), "SessionToken") { + t.Fatal("secret exposed") + } + s.mu.Lock() + retained := s.flows[started.FlowID].token + s.mu.Unlock() + if retained != "" { + t.Fatal("flow retained session token after completion") + } + if _, err := s.SelectLoginProject(started.FlowID, "project"); err == nil { + t.Fatal("duplicate provisioning admitted") + } +} + +func TestProviderLoginCancellationExpiryAndRestart(t *testing.T) { + for _, action := range []string{"cancel", "expire", "restart"} { + t.Run(action, func(t *testing.T) { + s := NewProviderService(t.Context(), "generation-a") + s.lifetime = 20 * time.Millisecond + s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { + <-ctx.Done() + return providerLoginIdentity{}, ctx.Err() + } + started, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + switch action { + case "cancel": + if _, err := s.CancelLogin(started.FlowID); err != nil { + t.Fatal(err) + } + waitProviderState(t, s, started.FlowID, "cancelled") + case "expire": + waitProviderState(t, s, started.FlowID, "expired") + case "restart": + s.Close() + next := NewProviderService(t.Context(), "generation-b") + defer next.Close() + status, err := next.LoginStatus(started.FlowID) + if err != nil || status.State != "interrupted" { + t.Fatalf("restart: %+v %v", status, err) + } + } + s.Close() + }) + } +} + +func TestProviderSetupRevisionAndSafeConfiguration(t *testing.T) { + t.Setenv("WHIPCODE_HOME", t.TempDir()) + s := NewProviderService(t.Context(), "generation") + defer s.Close() + s.validate = func(ctx context.Context, url, key string) ([]llm.ModelInfo, error) { + if key != "secret-key" { + return nil, errors.New("invalid key") + } + return []llm.ModelInfo{{ID: "fixture-chat-model"}}, nil + } + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "secret-key"}) + if err != nil { + t.Fatal(err) + } + if after.Revision == before.Revision { + t.Fatal("revision did not change") + } + if _, err := s.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: "secret-key"}); !errors.Is(err, config.ErrRevisionConflict) { + t.Fatalf("conflict: %v", err) + } + c, err := config.Load() + if err != nil { + t.Fatal(err) + } + if c.Providers["openrouter"].APIKey != "secret-key" { + t.Fatal("key not saved on host") + } + encoded, _ := json.Marshal(after) + if strings.Contains(string(encoded), "secret-key") { + t.Fatal("configuration exposed credential") + } +} + +func TestProviderLoginListRecoversLostAcknowledgementAndIsBounded(t *testing.T) { + s := NewProviderService(t.Context(), "generation") + defer s.Close() + s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { + <-ctx.Done() + return providerLoginIdentity{}, ctx.Err() + } + var first string + for range 64 { + flow, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + if first == "" { + first = flow.FlowID + recovered, err := s.BeginLogin() + if err != nil || recovered.FlowID != first || len(s.ListLogins().Flows) != 1 { + t.Fatal("lost begin acknowledgement did not recover the existing flow") + } + } + if _, err := s.CancelLogin(flow.FlowID); err != nil { + t.Fatal(err) + } + } + if _, err := s.BeginLogin(); err == nil { + t.Fatal("retained login bound was not enforced") + } + result := s.ListLogins() + if len(result.Flows) != 64 { + t.Fatal("retained login outcomes were lost") + } + s.mu.Lock() + s.flows[first].status.ExpiresAt = time.Now().Add(-time.Second) + s.mu.Unlock() + if _, err := s.BeginLogin(); err != nil { + t.Fatal("expired terminal login did not release capacity") + } +} + +func TestProviderFailureDoesNotExposeUpstreamSecret(t *testing.T) { + s := NewProviderService(t.Context(), "generation") + defer s.Close() + s.login = func(ctx context.Context, code func(string, string)) (providerLoginIdentity, error) { + return providerLoginIdentity{}, errors.New("upstream echoed secret-token") + } + result, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + result = waitProviderState(t, s, result.FlowID, "failed") + encoded, _ := json.Marshal(result) + if strings.Contains(string(encoded), "secret-token") { + t.Fatal("upstream secret exposed to client") + } +} + +func TestProviderLoginChangesWorkspaceBeforeProvisioning(t *testing.T) { + s := NewProviderService(t.Context(), "workspace-change") + defer s.Close() + s.login = func(context.Context, func(string, string)) (providerLoginIdentity, error) { + return providerLoginIdentity{token: "test-token", teams: []inferencenet.Team{{ID: "a"}, {ID: "b"}}}, nil + } + release := make(chan struct{}) + s.projects = func(ctx context.Context, _ string, team inferencenet.Team) ([]inferencenet.Project, error) { + if team.ID == "b" { + select { + case <-release: + case <-ctx.Done(): + return nil, ctx.Err() + } + } + return []inferencenet.Project{{ID: team.ID + "-1"}, {ID: team.ID + "-2"}}, nil + } + started, err := s.BeginLogin() + if err != nil { + t.Fatal(err) + } + waitProviderState(t, s, started.FlowID, "choose_team") + if _, err := s.SelectLoginTeam(started.FlowID, "a"); err != nil { + t.Fatal(err) + } + waitProviderState(t, s, started.FlowID, "choose_project") + loading, err := s.SelectLoginTeam(started.FlowID, "b") + if err != nil { + t.Fatal(err) + } + if loading.State != "loading_projects" || loading.TeamID != "b" || len(loading.Projects) != 0 { + t.Fatalf("retained previous workspace: %+v", loading) + } + if _, err := s.SelectLoginTeam(started.FlowID, "a"); err == nil { + t.Fatal("allowed overlapping project discovery") + } + close(release) + ready := waitProviderState(t, s, started.FlowID, "choose_project") + if len(ready.Projects) != 2 || ready.Projects[0].ID != "b-1" { + t.Fatalf("wrong workspace projects: %+v", ready.Projects) + } + if _, err := s.SelectLoginProject(started.FlowID, "a-1"); err == nil { + t.Fatal("accepted previous workspace project") + } + if _, err := s.CancelLogin(started.FlowID); err != nil { + t.Fatal(err) + } + if _, err := s.SelectLoginTeam(started.FlowID, "a"); err == nil { + t.Fatal("resumed a cancelled login") + } +} + +func compactionConfigurationFixture(t *testing.T) (*ProviderService, *config.Config) { + t.Helper() + t.Setenv("WHIPCODE_HOME", t.TempDir()) + t.Setenv("WHIP_TEST_MISSING_COMPACTION_KEY", "") + cfg := &config.Config{ + DefaultModel: "main", + Providers: map[string]config.Provider{ + "ready": {BaseURL: "https://ready.test/v1", Auth: "none"}, + "other": {BaseURL: "https://other.test/v1", Auth: "none"}, + "offline": {BaseURL: "https://offline.test/v1", APIKeyEnv: "WHIP_TEST_MISSING_COMPACTION_KEY"}, + "disabled": {BaseURL: "https://disabled.test/v1", Auth: "none"}, + }, + Models: map[string]config.Model{ + "main": {Providers: []string{"ready"}}, + "summary": {Providers: []string{"ready"}}, + "offline-summary": {Providers: []string{"offline"}}, + "disabled-summary": {Providers: []string{"disabled"}}, + }, + DisabledProviders: []string{"disabled"}, + } + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + if err := config.SaveCatalogs(map[string]config.Catalog{ + "ready": {BaseURL: "https://ready.test/v1", Models: []config.ModelInfoLite{ + {ID: "catalog-only"}, {ID: "ambiguous"}, + }}, + "other": {BaseURL: "https://other.test/v1", Models: []config.ModelInfoLite{{ID: "ambiguous"}}}, + }); err != nil { + t.Fatal(err) + } + s := NewProviderService(t.Context(), "compaction-settings") + t.Cleanup(s.Close) + return s, cfg +} + +func TestProviderCompactionConfigurationSelections(t *testing.T) { + tests := []struct { + name string + model string + provider string + wantProvider string + wantErr bool + }{ + {name: "alias resolves provider", model: "summary", wantProvider: "ready"}, + {name: "catalog resolves provider", model: "catalog-only", wantProvider: "ready"}, + {name: "explicit route", model: "summary", provider: "ready", wantProvider: "ready"}, + {name: "automatic clears provider", provider: "stale"}, + {name: "unknown model", model: "missing", provider: "ready", wantErr: true}, + {name: "unknown provider", model: "summary", provider: "missing", wantErr: true}, + {name: "missing credentials", model: "offline-summary", wantErr: true}, + {name: "disabled provider", model: "disabled-summary", wantErr: true}, + {name: "wrong provider", model: "summary", provider: "other", wantErr: true}, + {name: "ambiguous route", model: "ambiguous", wantErr: true}, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + s, _ := compactionConfigurationFixture(t) + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{ + Revision: before.Revision, CompactModel: &test.model, CompactProvider: &test.provider, + CompactPercent: new(60), MaxRetries: new(3), + }) + if (err != nil) != test.wantErr { + t.Fatalf("update error = %v, wantErr %t", err, test.wantErr) + } + persisted, readErr := s.ReadConfiguration() + if readErr != nil { + t.Fatal(readErr) + } + if test.wantErr { + if persisted.Revision != before.Revision { + t.Fatal("invalid route partially saved configuration") + } + return + } + if after.CompactModel != test.model || after.CompactProvider != test.wantProvider { + t.Fatalf("compaction selection = %q %q; want %q %q", + after.CompactModel, after.CompactProvider, test.model, test.wantProvider) + } + if persisted.CompactModel != after.CompactModel || persisted.CompactProvider != after.CompactProvider { + t.Fatal("resolved model and provider were not persisted together") + } + if after.CompactPercent != 60 || after.MaxRetries != 3 { + t.Fatal("valid settings were not saved atomically") + } + }) + } +} + +func TestProviderCompactionConfigurationPreservesUnchangedLegacyOverrides(t *testing.T) { + for _, model := range []string{"deepseek-v4-flash-0731", "missing-summary"} { + t.Run(model, func(t *testing.T) { + s, cfg := compactionConfigurationFixture(t) + cfg.CompactModel, cfg.CompactProvider, cfg.CompactPct = model, "missing-provider", 95 + if err := cfg.Save(); err != nil { + t.Fatal(err) + } + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{ + Revision: before.Revision, CompactModel: &before.CompactModel, + CompactProvider: &before.CompactProvider, CompactPercent: &before.CompactPercent, + DefaultModel: &before.DefaultModel, DefaultProvider: &before.DefaultProvider, MaxRetries: new(4), + }) + if err != nil { + t.Fatal(err) + } + if after.CompactModel != model || after.CompactProvider != "missing-provider" || after.CompactPercent != 95 || after.MaxRetries != 4 { + t.Fatalf("legacy override was changed: %+v", after) + } + if _, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{ + Revision: after.Revision, CompactProvider: new("different-missing-provider"), + }); err == nil { + t.Fatal("changed legacy route was not validated") + } + cleared, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{ + Revision: after.Revision, CompactModel: new(""), CompactProvider: &after.CompactProvider, + }) + if err != nil || cleared.CompactModel != "" || cleared.CompactProvider != "" { + t.Fatalf("automatic did not clear override: %+v %v", cleared, err) + } + }) + } +} + +func TestProviderCompactionConfigurationThresholdValidation(t *testing.T) { + for _, test := range []struct { + name string + percent int + wantErr bool + }{ + {name: "automatic"}, + {name: "minimum", percent: 10}, + {name: "maximum", percent: 90}, + {name: "negative", percent: -1, wantErr: true}, + {name: "below minimum", percent: 9, wantErr: true}, + {name: "above maximum", percent: 91, wantErr: true}, + {name: "over 100", percent: 101, wantErr: true}, + } { + t.Run(test.name, func(t *testing.T) { + s, _ := compactionConfigurationFixture(t) + before, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + after, err := s.UpdateConfiguration(protocol.ConfigurationUpdate{ + Revision: before.Revision, CompactPercent: &test.percent, MaxRetries: new(5), + }) + if (err != nil) != test.wantErr { + t.Fatalf("threshold error = %v, wantErr %t", err, test.wantErr) + } + if !test.wantErr && after.CompactPercent != test.percent { + t.Fatalf("threshold = %d, want %d", after.CompactPercent, test.percent) + } + persisted, err := s.ReadConfiguration() + if err != nil { + t.Fatal(err) + } + if test.wantErr && persisted.Revision != before.Revision { + t.Fatal("invalid threshold partially saved configuration") + } + }) + } +} From 4b5c0e5790f698371abed1ed4c8bcf3dd9cd3885 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:47:52 -0700 Subject: [PATCH 34/67] docs: record reordered backend stack and compatibility evidence --- docs/backend-reorganization-plan.md | 35 +++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index e3363f59c..3c0d8c902 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -649,20 +649,41 @@ prerequisite. The execution ledger below records subsequent repairs and results. ## Execution ledger -All PRs remain unmerged. Rebased dependency heads are recorded below; successful +All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. +The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 3b2. +The separate UI-readiness repair now precedes the compatibility gate so that +PR #302 inherits that repair in its own required CI. The combined tree at the +new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and +the 3b2 code commit likewise retain their previous complete trees. This ledger +update changes only documentation. Earlier SHA-specific evidence below remains +historical evidence; the reordered heads require fresh hosted results. +GitHub automatically marked historical PR #303 merged into its former stack +parent when the reordered parent contained its commit. Replacement PR #307 keeps +that separate repair reviewable against PR #301. No merge command ran, and +development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Step | Revision and PR | Evidence and status | | --- | --- | --- | | Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | | Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | | Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681286958) and current security passed. | -| Frozen-contract gate | `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [PR #302](https://github.com/context-labs/whip/pull/302) | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine data rollback. [Current full CI](https://github.com/context-labs/whip/actions/runs/36681287828) completed: both Linux/macOS compatibility jobs, Go tests with the 90% coverage floor, lint and runtime checks passed. The aggregate failed the independently reproduced UI scroll-readiness race repaired downstream in PR #303; current security passed. | -| Dialog assertion readiness | `1882979ad414c256cada7b2fb71e11a02f46bd4e`, [PR #303](https://github.com/context-labs/whip/pull/303) | Separate test-only repair waits for sheet focus before scroll assertions. The combined 36-test workflow-policy suite passed. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681287194) passed, including SDK/UI/browser/product, both compatibility jobs, Go tests with the 90% coverage floor, lint, runtime, mobile, builds, docs, desktop and distribution. Current security also passed; this is the combined green prerequisite baseline. | -| Host MCP ownership (plan PR 2) | `d8175212d3db3371b14862dc07ad24fc62393108`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The real HTTP cancellation characterization passed against the original implementation before extraction. Focused MCP/icon race tests, full-module build/vet/whipvet, and the full daemon race/shuffle suite (250.722s) passed. Fresh fixed-SDK comparisons passed against the original reference and immediate base `1882979ad414c256cada7b2fb71e11a02f46bd4e`, including both transports, mutation rejection, lifecycle and both-engine data rollback. [Full current CI](https://github.com/context-labs/whip/actions/runs/36682214774) and current security passed. | -| Provider operation boundary (plan PR 3a) | `a211fb0e7629f9692eb5133aa00244aea17e38a9`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog operation/reload characterization passed three times under the race detector on unchanged production code before extraction. Typed catalog results, compaction validation, model admission and provider-context borrowing now form the narrow operation surface. Shared effort and permission-default helpers move once to their existing configuration/session owners. Validation results are recorded below. [Current CI](https://github.com/context-labs/whip/actions/runs/36683418233) is running; current security passed. | -| Provider integration test boundary (plan PR 3b1) | `d81f814b139d3a2320db6942e02c22a3e54d9b80`, [PR #306](https://github.com/context-labs/whip/pull/306). | The five existing affected integration tests now use HTTP/auth persistence rather than private provider callbacks. They passed three times under the race detector (23.256s). Full-module build, vet and whipvet and fresh fixed-SDK compatibility passed. The full daemon race/shuffle suite passed (261.125s). [Current CI](https://github.com/context-labs/whip/actions/runs/36684285340) is running; current security passed. | -| Provider package extraction (plan PR 3b2) | This change, based on `d81f814b139d3a2320db6942e02c22a3e54d9b80`. | Eleven implementation files move to `internal/provider` with their existing service and constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing test functions remain. Provider-private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. Validation results are recorded below. | +| Dialog assertion readiness | `722b49321f3cb2a70c8d829911279ffd79caf0a0`, [PR #307](https://github.com/context-labs/whip/pull/307), based on PR #301. | Separate test-only repair waits for sheet focus before scroll assertions. The prior combined head `1882979ad414c256cada7b2fb71e11a02f46bd4e` passed the 36-test workflow-policy suite, [full CI](https://github.com/context-labs/whip/actions/runs/36681287194) and security, including both compatibility jobs and the 90% coverage floor. This repair now precedes the guard; [reordered-head CI](https://github.com/context-labs/whip/actions/runs/36685631006) is pending. | +| Frozen-contract gate | `8f0230444eb447e87c619d7c689eca811ac5d1f3`, [PR #302](https://github.com/context-labs/whip/pull/302), based on PR #307. | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine rollback. At historical head `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [CI](https://github.com/context-labs/whip/actions/runs/36681287828) passed both compatibility jobs, Go coverage, lint and runtime but failed the independently reproduced UI race. The new head includes the separate repair and has the exact previously green combined prerequisite tree. [Fresh CI](https://github.com/context-labs/whip/actions/runs/36685509442) remains pending. | +| Host MCP ownership (plan PR 2) | `bfd030fb7bee920982c8d0ab9f6a4820be962166`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The original-implementation cancellation characterization, focused MCP/icon race tests, build/vet/whipvet, full daemon race/shuffle (250.722s), and fixed/immediate-base compatibility passed. Historical head `d8175212d3db3371b14862dc07ad24fc62393108` passed [full CI](https://github.com/context-labs/whip/actions/runs/36682214774) and security. Its tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685511446) is pending. | +| Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685508710) is pending. | +| Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685511450) is pending. | +| Provider package extraction (plan PR 3b2) | Code commit `98a2401cbf8a75cc9fe79c224b28427bde2b3b77`, based on `675717575868c5b3b9bf2da1a9b2863238b12a28`. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent; hosted CI has not yet started. | + +Fresh post-reorder evidence is recorded at +`/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed +reference `271c0f8d2a35648d1b45056d57432590b783483c`, immediate parent +`675717575868c5b3b9bf2da1a9b2863238b12a28`, and candidate code commit +`98a2401cbf8a75cc9fe79c224b28427bde2b3b77`. Fresh fixed/parent/candidate binaries +passed both transport comparisons, response/order mutation rejection, lifecycle +checks, and both-engine retained-root/child/content/schema/trace rollback. +The following commit updates only this ledger; its product and test source +remains identical to that recorded candidate. ### Host MCP ownership and lifetime From b251786c8d868cba722f103d0a77ce72d07377f5 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 00:57:03 -0700 Subject: [PATCH 35/67] refactor(cli): separate daemon runtime construction --- cmd/whip/daemon.go | 262 +------------------------ cmd/whip/daemon_runtime.go | 284 ++++++++++++++++++++++++++++ docs/backend-reorganization-plan.md | 56 +++++- docs/features.md | 2 +- 4 files changed, 334 insertions(+), 270 deletions(-) create mode 100644 cmd/whip/daemon_runtime.go diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index a6c8aed7f..d13e9791d 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -8,30 +8,18 @@ import ( "os" "os/signal" "path/filepath" - "slices" "strconv" - "strings" "sync" "syscall" - "time" "github.com/context-labs/whip/internal/buildinfo" providersvc "github.com/context-labs/whip/internal/provider" - "github.com/context-labs/whip/internal/agent" - "github.com/context-labs/whip/internal/agentdef" - "github.com/context-labs/whip/internal/browser" - "github.com/context-labs/whip/internal/computer" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/lsp" - "github.com/context-labs/whip/internal/mcp" - "github.com/context-labs/whip/internal/openaiauth" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" - "github.com/context-labs/whip/internal/tools" "github.com/context-labs/whip/internal/webgateway" ) @@ -104,98 +92,7 @@ func runDaemon(ctx context.Context, args []string) error { } kernels := rlm.NewManager(limits.MaxWorkers) defer kernels.Close() - factory := func(ctx context.Context, meta session.Meta, history []llm.Message) (daemon.Components, error) { - runtimeCfg, err := config.Load() - if err != nil { - return daemon.Components{}, err - } - // Hand edits to the allowlist take effect on the next session. - store.SetGlobalPermissionRules(runtimeCfg.Permissions.Allow) - if meta.Kind == session.SessionKindToolHost { - services := daemonToolServices(runtimeCfg, meta, "mcp", agentdef.Capabilities) - return daemon.Components{Runner: daemon.NewToolRunner(services)}, nil - } - definition, ok, err := daemon.DefinitionFor(ctx, store, meta) - if err != nil { - return daemon.Components{}, err - } - if !ok { - return daemon.Components{}, fmt.Errorf("unsupported session kind %q", meta.Kind) - } - route, model, err := resolveRuntimeModel(runtimeCfg, meta.Model, meta.Provider, providers) - if err != nil { - return daemon.Components{}, err - } - services := daemonToolServices(runtimeCfg, meta, route.Model, definition.Capabilities) - ag := agent.NewRuntime(route.Client, route.Model, route.MaxTokens, "", services) - ag.ModelName, ag.Provider = route.ModelName, route.Provider - ag.Pricing = route.Pricing - ag.WorkingDir = meta.CWD - ag.ContextLimit = route.ContextLimit - if model.SamplingParams != nil { - ag.Temperature, ag.TopP = model.SamplingParams.Temperature, model.SamplingParams.TopP - } - if route.Vision { - services.SetScreenshotSink(func(images [][]byte) { - ag.SteerImages("images attached (browser/computer screenshots or MCP results):", screenshotParts(images)) - }) - } - ag.Vision = route.Vision - // The saved effort is concrete: the daemon resolves it at creation and - // upgrades older blank rows at open. "off" becomes an omitted parameter - // at the request boundary. - ag.Effort = meta.Effort - ag.ResolveModel = func(model, provider string) (agent.ModelRoute, error) { - currentCfg, loadErr := config.Load() - if loadErr != nil { - return agent.ModelRoute{}, loadErr - } - resolved, _, resolveErr := resolveRuntimeModel(currentCfg, model, provider, providers) - return resolved, resolveErr - } - configureRuntimeCompaction(ag, runtimeCfg, definition.Compaction, providers) - var mcpManager *mcp.Manager - discovery := mcp.LoadMergedFiltered(meta.CWD, mcp.FromConfigMap(runtimeCfg.MCPServers), mcp.ImportPolicyFrom(runtimeCfg.MCPImport)) - // The definition names the servers it uses; everything else the host - // configured stays out of this session. Attachment applies the same step. - discovery = mcp.Select(discovery, definition.MCP.Servers) - for source, err := range discovery.Errs { - config.LogEvent("mcp", fmt.Sprintf("discovery: %s: %v", source, err)) - } - if len(discovery.Merged) > 0 || len(discovery.Blocked) > 0 || len(discovery.Errs) > 0 { - mcpManager = mcp.NewManager(discovery.Merged) - mcpManager.SetBlocked(discovery.Blocked) - mcpManager.SetSourceErrors(discovery.Errs) - } - runtime, err := daemon.NewRecursiveRuntime(daemon.RecursiveRuntimeOptions{ - Engine: meta.ExecutionEngine, Definition: definition, Agent: ag, History: history, Limits: limits, Kernels: kernels, - KernelCommand: daemonKernelCommand, - }) - if err != nil { - if mcpManager != nil { - mcpManager.Close() - } - services.Close() - return daemon.Components{}, err - } - components := daemon.Components{ - Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: definition, - LoadMCP: func(ctx context.Context) (mcp.Filtered, error) { - if err := ctx.Err(); err != nil { - return mcp.Filtered{}, err - } - fresh, err := config.Load() - if err != nil { - return mcp.Filtered{}, err - } - return mcp.LoadMergedFiltered(meta.CWD, mcp.FromConfigMap(fresh.MCPServers), mcp.ImportPolicyFrom(fresh.MCPImport)), ctx.Err() - }, - } - if mcpManager != nil { - components.MCP = mcpManager - } - return components, nil - } + factory := daemonRuntimeFactory(store, providers, kernels, limits) ownerDaemon, err := daemon.New(store, factory, providers) if err != nil { _ = store.Close() @@ -261,163 +158,6 @@ func runDaemon(ctx context.Context, args []string) error { } } -// configureRuntimeCompaction leaves Automatic on the conversation's actual route. -func configureRuntimeCompaction( - ag *agent.Agent, - cfg *config.Config, - defaults agentdef.CompactionDefaults, - providers *providersvc.ProviderService, -) { - ag.CompactThreshold = defaults.Threshold - if ag.CompactThreshold == 0 { - percent := cfg.CompactPct - if percent == 0 { - percent = config.DefaultCompactPct - } - ag.CompactThreshold = float64(min(max(percent, 10), 90)) / 100 - } - model, provider := defaults.Model, defaults.Provider - if model == "" { - model, provider = cfg.CompactModel, cfg.CompactProvider - } - if model == "" { - return - } - compact, _, err := resolveRuntimeModel(cfg, model, provider, providers) - if err != nil { - ag.CompactFallback = "Custom summarizer unavailable; using this conversation’s model." - config.LogEvent("compaction.fallback", fmt.Sprintf( - "compact model %q (provider %q) unavailable, summaries run on the conversation model: %v", - model, provider, err, - )) - return - } - ag.CompactClient = compact.Client - ag.CompactModel, ag.CompactProvider = compact.Model, compact.Provider - ag.CompactPricing = compact.Pricing - ag.CompactContextLimit, ag.CompactMaxTokens = compact.ContextLimit, compact.MaxTokens -} - -// resolveRuntimeModel snapshots the actual endpoint and its catalog rates together. -// All model purposes use this resolver so a default provider cannot accidentally -// supply another endpoint's price or output limits. -func resolveRuntimeModel(cfg *config.Config, modelName, providerName string, services ...*providersvc.ProviderService) (agent.ModelRoute, config.Model, error) { - providerName, provider, model, apiID, err := cfg.ResolveRoute(modelName, providerName) - if err != nil { - return agent.ModelRoute{}, config.Model{}, err - } - if modelName == "" { - modelName = cfg.DefaultModel - } - var providers *providersvc.ProviderService - if len(services) > 0 { - providers = services[0] - } - catalog := providers.CatalogsFor(cfg)[providerName] - if len(model.Providers) > 0 && !slices.Contains(model.Providers, providerName) && catalog.Find(apiID) == nil { - return agent.ModelRoute{}, config.Model{}, fmt.Errorf("model %q is not advertised by provider %q; select a model on that provider", apiID, providerName) - } - client, err := providers.ModelClient(provider, cfg) - if err != nil { - return agent.ModelRoute{}, config.Model{}, err - } - contextLimit, maxOutput := catalog.ModelLimits(apiID, model) - if provider.API == openaiauth.Provider { - maxOutput = llm.SubscriptionOutputLimit(apiID) - if maxOutput == 0 || (model.MaxOut > 0 && model.MaxOut < maxOutput) { - return agent.ModelRoute{}, config.Model{}, errors.New("ChatGPT subscription route requires a verified model limit and cannot enforce a smaller maxOut") - } - } - vision := model.Vision - if advertised, found := catalog.SupportsVision(apiID); found { - vision = advertised - } - client.MaxRetries = cfg.MaxRetries - pricing := llm.Pricing{} - if provider.API != openaiauth.Provider && strings.TrimRight(catalog.BaseURL, "/") == client.BaseURL { - pricing = catalog.ModelPricing(apiID) - } - return agent.ModelRoute{ - Client: client, ModelName: modelName, Provider: providerName, Model: apiID, - ContextLimit: contextLimit, MaxTokens: maxOutput, Vision: vision, - Pricing: pricing, - }, model, nil -} - -// daemonToolServices wires host integrations for one session. Browser and -// computer automation follow the definition's capabilities; the host -// configuration can still disable them. -func daemonToolServices(cfg *config.Config, meta session.Meta, apiID string, capabilities []string) *tools.Services { - services := tools.NewServices() - services.SetExternalPermissions(true) - services.SetProcessMarkers(meta.ID, apiID) - if cfg.Browser.CDPURL != "" { - services.SetProcessEnvironment(map[string]string{"WHIP_CDP_URL": cfg.Browser.CDPURL}) - } - if slices.Contains(capabilities, "browser") && (cfg.Browser.Enabled == nil || *cfg.Browser.Enabled) { - mode := browser.ModeLive - switch cfg.Browser.Mode { - case "dedicated": - mode = browser.ModeDedicated - case "headless": - mode = browser.ModeHeadless - case "extension": - mode = browser.ModeExtension - } - manager := browser.NewManager(mode) - if cfg.Browser.Driver != "" { - manager.SwitchDriver(cfg.Browser.Driver) - } - services.SetBrowser(manager, cfg.Browser.AllowPrivateURLs) - } - if slices.Contains(capabilities, "computer") && (cfg.Computer.Enabled == nil || *cfg.Computer.Enabled) { - defaultDeny := cfg.Computer.DefaultDeny != nil && *cfg.Computer.DefaultDeny - services.SetComputerPolicy(computer.NewPolicy(cfg.Computer.Allow, cfg.Computer.Deny, defaultDeny)) - } - services.SetDiagnostics(lsp.NewManager(lsp.FromConfigMap(cfg.LSPServers))) - return services -} - -func rlmLimits(value config.RLMConfig) rlm.Limits { - limits := rlm.DefaultLimits() - if value.MaxConcurrentHostCalls != 0 { - limits.MaxConcurrentHostCalls = value.MaxConcurrentHostCalls - } - if value.Steps > 0 { - limits.Steps = value.Steps - } - if value.HostRequests > 0 { - limits.HostRequests = value.HostRequests - } - if value.WallMillis > 0 { - limits.Wall = time.Duration(value.WallMillis) * time.Millisecond - } - if value.MemoryMiB > 0 { - limits.MemoryBytes = uint64(value.MemoryMiB) << 20 - } - if value.OutputBytes > 0 { - limits.OutputBytes = value.OutputBytes - } - if value.FrameBytes > 0 { - limits.FrameBytes = value.FrameBytes - } - if value.MaxWorkers > 0 { - limits.MaxWorkers = value.MaxWorkers - } - return limits -} - -// screenshotParts bounds captures like every other image entering history: a -// HiDPI full-display shot exceeds both the dimension and byte caps. -func screenshotParts(images [][]byte) []llm.ContentPart { - parts := make([]llm.ContentPart, 0, len(images)) - for _, image := range images { - ext, data := llm.NormalizeImage("jpg", image) - parts = append(parts, llm.ImagePart(ext, data)) - } - return parts -} - // Automatic gateway startup is opt-in. Terminal authority remains daemon-owned // and is independent of whether this daemon owns a gateway child. type daemonNetworkOptions struct { diff --git a/cmd/whip/daemon_runtime.go b/cmd/whip/daemon_runtime.go new file mode 100644 index 000000000..124653712 --- /dev/null +++ b/cmd/whip/daemon_runtime.go @@ -0,0 +1,284 @@ +package main + +import ( + "context" + "errors" + "fmt" + "slices" + "strings" + "time" + + "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/agentdef" + "github.com/context-labs/whip/internal/browser" + "github.com/context-labs/whip/internal/computer" + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/lsp" + "github.com/context-labs/whip/internal/mcp" + "github.com/context-labs/whip/internal/openaiauth" + providersvc "github.com/context-labs/whip/internal/provider" + "github.com/context-labs/whip/internal/rlm" + "github.com/context-labs/whip/internal/session" + "github.com/context-labs/whip/internal/tools" +) + +// daemonRuntimeFactory borrows startup resources and constructs session components +// for the daemon to own. +func daemonRuntimeFactory( + store *session.Store, + providers *providersvc.ProviderService, + kernels *rlm.Manager, + limits rlm.Limits, +) daemon.Factory { + return func(ctx context.Context, meta session.Meta, history []llm.Message) (daemon.Components, error) { + runtimeCfg, err := config.Load() + if err != nil { + return daemon.Components{}, err + } + // Hand edits to the allowlist take effect on the next session. + store.SetGlobalPermissionRules(runtimeCfg.Permissions.Allow) + if meta.Kind == session.SessionKindToolHost { + services := daemonToolServices(runtimeCfg, meta, "mcp", agentdef.Capabilities) + return daemon.Components{Runner: daemon.NewToolRunner(services)}, nil + } + definition, ok, err := daemon.DefinitionFor(ctx, store, meta) + if err != nil { + return daemon.Components{}, err + } + if !ok { + return daemon.Components{}, fmt.Errorf("unsupported session kind %q", meta.Kind) + } + route, model, err := resolveRuntimeModel(runtimeCfg, meta.Model, meta.Provider, providers) + if err != nil { + return daemon.Components{}, err + } + services := daemonToolServices(runtimeCfg, meta, route.Model, definition.Capabilities) + ag := agent.NewRuntime(route.Client, route.Model, route.MaxTokens, "", services) + ag.ModelName, ag.Provider = route.ModelName, route.Provider + ag.Pricing = route.Pricing + ag.WorkingDir = meta.CWD + ag.ContextLimit = route.ContextLimit + if model.SamplingParams != nil { + ag.Temperature, ag.TopP = model.SamplingParams.Temperature, model.SamplingParams.TopP + } + if route.Vision { + services.SetScreenshotSink(func(images [][]byte) { + ag.SteerImages("images attached (browser/computer screenshots or MCP results):", screenshotParts(images)) + }) + } + ag.Vision = route.Vision + // The saved effort is concrete: the daemon resolves it at creation and + // upgrades older blank rows at open. "off" becomes an omitted parameter + // at the request boundary. + ag.Effort = meta.Effort + ag.ResolveModel = func(model, provider string) (agent.ModelRoute, error) { + currentCfg, loadErr := config.Load() + if loadErr != nil { + return agent.ModelRoute{}, loadErr + } + resolved, _, resolveErr := resolveRuntimeModel(currentCfg, model, provider, providers) + return resolved, resolveErr + } + configureRuntimeCompaction(ag, runtimeCfg, definition.Compaction, providers) + var mcpManager *mcp.Manager + discovery := mcp.LoadMergedFiltered(meta.CWD, mcp.FromConfigMap(runtimeCfg.MCPServers), mcp.ImportPolicyFrom(runtimeCfg.MCPImport)) + // The definition names the servers it uses; everything else the host + // configured stays out of this session. Attachment applies the same step. + discovery = mcp.Select(discovery, definition.MCP.Servers) + for source, err := range discovery.Errs { + config.LogEvent("mcp", fmt.Sprintf("discovery: %s: %v", source, err)) + } + if len(discovery.Merged) > 0 || len(discovery.Blocked) > 0 || len(discovery.Errs) > 0 { + mcpManager = mcp.NewManager(discovery.Merged) + mcpManager.SetBlocked(discovery.Blocked) + mcpManager.SetSourceErrors(discovery.Errs) + } + runtime, err := daemon.NewRecursiveRuntime(daemon.RecursiveRuntimeOptions{ + Engine: meta.ExecutionEngine, Definition: definition, Agent: ag, History: history, Limits: limits, Kernels: kernels, + KernelCommand: daemonKernelCommand, + }) + if err != nil { + if mcpManager != nil { + mcpManager.Close() + } + services.Close() + return daemon.Components{}, err + } + components := daemon.Components{ + Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: definition, + LoadMCP: func(ctx context.Context) (mcp.Filtered, error) { + if err := ctx.Err(); err != nil { + return mcp.Filtered{}, err + } + fresh, err := config.Load() + if err != nil { + return mcp.Filtered{}, err + } + return mcp.LoadMergedFiltered(meta.CWD, mcp.FromConfigMap(fresh.MCPServers), mcp.ImportPolicyFrom(fresh.MCPImport)), ctx.Err() + }, + } + if mcpManager != nil { + components.MCP = mcpManager + } + return components, nil + } +} + +// configureRuntimeCompaction leaves Automatic on the conversation's actual route. +func configureRuntimeCompaction( + ag *agent.Agent, + cfg *config.Config, + defaults agentdef.CompactionDefaults, + providers *providersvc.ProviderService, +) { + ag.CompactThreshold = defaults.Threshold + if ag.CompactThreshold == 0 { + percent := cfg.CompactPct + if percent == 0 { + percent = config.DefaultCompactPct + } + ag.CompactThreshold = float64(min(max(percent, 10), 90)) / 100 + } + model, provider := defaults.Model, defaults.Provider + if model == "" { + model, provider = cfg.CompactModel, cfg.CompactProvider + } + if model == "" { + return + } + compact, _, err := resolveRuntimeModel(cfg, model, provider, providers) + if err != nil { + ag.CompactFallback = "Custom summarizer unavailable; using this conversation’s model." + config.LogEvent("compaction.fallback", fmt.Sprintf( + "compact model %q (provider %q) unavailable, summaries run on the conversation model: %v", + model, provider, err, + )) + return + } + ag.CompactClient = compact.Client + ag.CompactModel, ag.CompactProvider = compact.Model, compact.Provider + ag.CompactPricing = compact.Pricing + ag.CompactContextLimit, ag.CompactMaxTokens = compact.ContextLimit, compact.MaxTokens +} + +// resolveRuntimeModel snapshots the actual endpoint and its catalog rates together. +// All model purposes use this resolver so a default provider cannot accidentally +// supply another endpoint's price or output limits. +func resolveRuntimeModel(cfg *config.Config, modelName, providerName string, services ...*providersvc.ProviderService) (agent.ModelRoute, config.Model, error) { + providerName, provider, model, apiID, err := cfg.ResolveRoute(modelName, providerName) + if err != nil { + return agent.ModelRoute{}, config.Model{}, err + } + if modelName == "" { + modelName = cfg.DefaultModel + } + var providers *providersvc.ProviderService + if len(services) > 0 { + providers = services[0] + } + catalog := providers.CatalogsFor(cfg)[providerName] + if len(model.Providers) > 0 && !slices.Contains(model.Providers, providerName) && catalog.Find(apiID) == nil { + return agent.ModelRoute{}, config.Model{}, fmt.Errorf("model %q is not advertised by provider %q; select a model on that provider", apiID, providerName) + } + client, err := providers.ModelClient(provider, cfg) + if err != nil { + return agent.ModelRoute{}, config.Model{}, err + } + contextLimit, maxOutput := catalog.ModelLimits(apiID, model) + if provider.API == openaiauth.Provider { + maxOutput = llm.SubscriptionOutputLimit(apiID) + if maxOutput == 0 || (model.MaxOut > 0 && model.MaxOut < maxOutput) { + return agent.ModelRoute{}, config.Model{}, errors.New("ChatGPT subscription route requires a verified model limit and cannot enforce a smaller maxOut") + } + } + vision := model.Vision + if advertised, found := catalog.SupportsVision(apiID); found { + vision = advertised + } + client.MaxRetries = cfg.MaxRetries + pricing := llm.Pricing{} + if provider.API != openaiauth.Provider && strings.TrimRight(catalog.BaseURL, "/") == client.BaseURL { + pricing = catalog.ModelPricing(apiID) + } + return agent.ModelRoute{ + Client: client, ModelName: modelName, Provider: providerName, Model: apiID, + ContextLimit: contextLimit, MaxTokens: maxOutput, Vision: vision, + Pricing: pricing, + }, model, nil +} + +// daemonToolServices wires host integrations for one session. Browser and +// computer automation follow the definition's capabilities; the host +// configuration can still disable them. +func daemonToolServices(cfg *config.Config, meta session.Meta, apiID string, capabilities []string) *tools.Services { + services := tools.NewServices() + services.SetExternalPermissions(true) + services.SetProcessMarkers(meta.ID, apiID) + if cfg.Browser.CDPURL != "" { + services.SetProcessEnvironment(map[string]string{"WHIP_CDP_URL": cfg.Browser.CDPURL}) + } + if slices.Contains(capabilities, "browser") && (cfg.Browser.Enabled == nil || *cfg.Browser.Enabled) { + mode := browser.ModeLive + switch cfg.Browser.Mode { + case "dedicated": + mode = browser.ModeDedicated + case "headless": + mode = browser.ModeHeadless + case "extension": + mode = browser.ModeExtension + } + manager := browser.NewManager(mode) + if cfg.Browser.Driver != "" { + manager.SwitchDriver(cfg.Browser.Driver) + } + services.SetBrowser(manager, cfg.Browser.AllowPrivateURLs) + } + if slices.Contains(capabilities, "computer") && (cfg.Computer.Enabled == nil || *cfg.Computer.Enabled) { + defaultDeny := cfg.Computer.DefaultDeny != nil && *cfg.Computer.DefaultDeny + services.SetComputerPolicy(computer.NewPolicy(cfg.Computer.Allow, cfg.Computer.Deny, defaultDeny)) + } + services.SetDiagnostics(lsp.NewManager(lsp.FromConfigMap(cfg.LSPServers))) + return services +} + +func rlmLimits(value config.RLMConfig) rlm.Limits { + limits := rlm.DefaultLimits() + if value.MaxConcurrentHostCalls != 0 { + limits.MaxConcurrentHostCalls = value.MaxConcurrentHostCalls + } + if value.Steps > 0 { + limits.Steps = value.Steps + } + if value.HostRequests > 0 { + limits.HostRequests = value.HostRequests + } + if value.WallMillis > 0 { + limits.Wall = time.Duration(value.WallMillis) * time.Millisecond + } + if value.MemoryMiB > 0 { + limits.MemoryBytes = uint64(value.MemoryMiB) << 20 + } + if value.OutputBytes > 0 { + limits.OutputBytes = value.OutputBytes + } + if value.FrameBytes > 0 { + limits.FrameBytes = value.FrameBytes + } + if value.MaxWorkers > 0 { + limits.MaxWorkers = value.MaxWorkers + } + return limits +} + +// screenshotParts bounds captures like every other image entering history: a +// HiDPI full-display shot exceeds both the dimension and byte caps. +func screenshotParts(images [][]byte) []llm.ContentPart { + parts := make([]llm.ContentPart, 0, len(images)) + for _, image := range images { + ext, data := llm.NormalizeImage("jpg", image) + parts = append(parts, llm.ImagePart(ext, data)) + } + return parts +} diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 3c0d8c902..3860379a9 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -651,12 +651,12 @@ prerequisite. The execution ledger below records subsequent repairs and results. All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. -The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 3b2. +The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 4a. The separate UI-readiness repair now precedes the compatibility gate so that PR #302 inherits that repair in its own required CI. The combined tree at the new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and -the 3b2 code commit likewise retain their previous complete trees. This ledger -update changes only documentation. Earlier SHA-specific evidence below remains +the 3b2 code commit likewise retain their previous complete trees. The reorder's +ledger update changed only documentation. Earlier SHA-specific evidence below remains historical evidence; the reordered heads require fresh hosted results. GitHub automatically marked historical PR #303 merged into its former stack parent when the reordered parent contained its commit. Replacement PR #307 keeps @@ -669,11 +669,12 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | | Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681286958) and current security passed. | | Dialog assertion readiness | `722b49321f3cb2a70c8d829911279ffd79caf0a0`, [PR #307](https://github.com/context-labs/whip/pull/307), based on PR #301. | Separate test-only repair waits for sheet focus before scroll assertions. The prior combined head `1882979ad414c256cada7b2fb71e11a02f46bd4e` passed the 36-test workflow-policy suite, [full CI](https://github.com/context-labs/whip/actions/runs/36681287194) and security, including both compatibility jobs and the 90% coverage floor. This repair now precedes the guard; [reordered-head CI](https://github.com/context-labs/whip/actions/runs/36685631006) is pending. | -| Frozen-contract gate | `8f0230444eb447e87c619d7c689eca811ac5d1f3`, [PR #302](https://github.com/context-labs/whip/pull/302), based on PR #307. | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine rollback. At historical head `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [CI](https://github.com/context-labs/whip/actions/runs/36681287828) passed both compatibility jobs, Go coverage, lint and runtime but failed the independently reproduced UI race. The new head includes the separate repair and has the exact previously green combined prerequisite tree. [Fresh CI](https://github.com/context-labs/whip/actions/runs/36685509442) remains pending. | -| Host MCP ownership (plan PR 2) | `bfd030fb7bee920982c8d0ab9f6a4820be962166`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The original-implementation cancellation characterization, focused MCP/icon race tests, build/vet/whipvet, full daemon race/shuffle (250.722s), and fixed/immediate-base compatibility passed. Historical head `d8175212d3db3371b14862dc07ad24fc62393108` passed [full CI](https://github.com/context-labs/whip/actions/runs/36682214774) and security. Its tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685511446) is pending. | -| Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685508710) is pending. | -| Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36685511450) is pending. | -| Provider package extraction (plan PR 3b2) | Code commit `98a2401cbf8a75cc9fe79c224b28427bde2b3b77`, based on `675717575868c5b3b9bf2da1a9b2863238b12a28`. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent; hosted CI has not yet started. | +| Frozen-contract gate | `8f0230444eb447e87c619d7c689eca811ac5d1f3`, [PR #302](https://github.com/context-labs/whip/pull/302), based on PR #307. | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine rollback. At historical head `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [CI](https://github.com/context-labs/whip/actions/runs/36681287828) passed both compatibility jobs, Go coverage, lint and runtime but failed the independently reproduced UI race. The new head includes the separate repair and has the exact previously green combined prerequisite tree. [Fresh CI](https://github.com/context-labs/whip/actions/runs/36686140019) remains pending. | +| Host MCP ownership (plan PR 2) | `bfd030fb7bee920982c8d0ab9f6a4820be962166`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The original-implementation cancellation characterization, focused MCP/icon race tests, build/vet/whipvet, full daemon race/shuffle (250.722s), and fixed/immediate-base compatibility passed. Historical head `d8175212d3db3371b14862dc07ad24fc62393108` passed [full CI](https://github.com/context-labs/whip/actions/runs/36682214774) and security. Its tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686146852) is pending. | +| Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686153135) is pending. | +| Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686160171) is pending. | +| Provider package extraction (plan PR 3b2) | `355b792bc99567068e65fdd0fd9f992a5b50ea0c`, [PR #308](https://github.com/context-labs/whip/pull/308), based on PR #306. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) is pending; security passed. | +| Startup factory extraction (plan PR 4a) | `codex/backend-reorg-04a-startup`, based on PR #308 (`355b792bc99567068e65fdd0fd9f992a5b50ea0c`). | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. Hosted checks follow publication. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -803,3 +804,42 @@ and ordering mutation rejection, lifecycle checks, and both-engine retained root/child/content/schema/trace rollback. All new files were staged before the run captured its candidate diff. Later ledger additions record these results; production and test source match the captured candidate. + + +### Startup factory extraction (plan PR 4a) + +`cmd/whip/daemon.go` now contains the startup and shutdown sequence in 186 lines; +`daemon_runtime.go` contains runtime, tool, model, MCP and compaction assembly. +The only new function, `daemonRuntimeFactory`, returns the existing +`daemon.Factory` and borrows the same store, provider service, kernel manager and +limits. The daemon owns the returned session components. Startup still owns +its locks and deferred provider/kernel cleanup; no new lifetime or interface is +introduced. + +The Go AST-directed move preserved the complete factory literal and all five +helper declarations byte for byte. The `runDaemon` token stream is unchanged +apart from replacing its factory assignment. Config reloads, MCP discovery, +model/provider/effort options and partial failure cleanup remain in their +original order. `daemonKernelCommand` is still read inside each factory +invocation. The existing CLI test files are unchanged, and the compaction guide +now points to the helper's new file. + +Validation passed: `go build ./...`, `go vet ./...`, +`go run ./cmd/whipvet ./...`, and the full +`go test -race -shuffle=on -count=1 ./cmd/whip` suite (71.763s). The CLI suite +exercises the moved construction code; the independent compatibility guard +continues to exercise the daemon integration fixture. No new tests were needed +for the unchanged bodies. + +Fresh guard evidence is at +`/private/tmp/whip-backend-compat-pr4a-fresh/evidence.json`: fixed SDK/reference +`271c0f8d2a35648d1b45056d57432590b783483c` and immediate parent +`355b792bc99567068e65fdd0fd9f992a5b50ea0c`, with Go 1.27.0 on darwin/arm64 and +Node 24.14.1. The staged source move is recorded in `candidateDiff`; the +precommit `candidateRevision` is the parent. Later documentation updates record +the results without changing the tested source. The fresh candidate daemon +binary SHA-256 is +`64623692653b4046145dae98e7ea4fcf94820bd6c19383a8f1ff531a157b322c`. +Both transport comparisons, deliberate response/order mutation rejection, +cancellation/reconnect checks and fixed/immediate-base rollback passed. Rollback +covers both engines, retained root/child state, content, schema and trace/export. diff --git a/docs/features.md b/docs/features.md index cad64fe02..21aa71c1a 100644 --- a/docs/features.md +++ b/docs/features.md @@ -147,7 +147,7 @@ Available modules are summarized in [tools.md](tools.md). reason on the summary's trace. Cancellation, uncertain completion, partial output and accounting/budget failures never cause a second-route replay. See [compaction settings](models-providers.md#compaction-model), - `cmd/whip/daemon.go`, `internal/agent/agent.go`, + `cmd/whip/daemon_runtime.go`, `internal/agent/agent.go`, `packages/app/src/settings/configuration.tsx`, and their configuration, compaction-fallback and settings regression tests. - Large values are immutable, content-addressed, and separately authorized. From 774623f12ef182856862209d186bc70150d17cf1 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:02:26 -0700 Subject: [PATCH 36/67] refactor(daemon): group host directory operations --- docs/backend-reorganization-plan.md | 42 ++++++- docs/features.md | 6 +- internal/daemon/host.go | 175 -------------------------- internal/daemon/host_directory.go | 185 ++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 179 deletions(-) create mode 100644 internal/daemon/host_directory.go diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 3860379a9..b09616806 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -674,7 +674,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686153135) is pending. | | Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686160171) is pending. | | Provider package extraction (plan PR 3b2) | `355b792bc99567068e65fdd0fd9f992a5b50ea0c`, [PR #308](https://github.com/context-labs/whip/pull/308), based on PR #306. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) is pending; security passed. | -| Startup factory extraction (plan PR 4a) | `codex/backend-reorg-04a-startup`, based on PR #308 (`355b792bc99567068e65fdd0fd9f992a5b50ea0c`). | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. Hosted checks follow publication. | +| Startup factory extraction (plan PR 4a) | `13493cf20dd84c7c97a18d33b1a6202d849eae94`, [PR #309](https://github.com/context-labs/whip/pull/309), based on PR #308. | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. | +| Host directory grouping (plan PR 4b) | `codex/backend-reorg-04b-host-directory`, based on PR #309 (`13493cf20dd84c7c97a18d33b1a6202d849eae94`). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. Hosted checks follow publication. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -843,3 +844,42 @@ binary SHA-256 is Both transport comparisons, deliberate response/order mutation rejection, cancellation/reconnect checks and fixed/immediate-base rollback passed. Rollback covers both engines, retained root/child state, content, schema and trace/export. + + +### Host directory grouping (plan PR 4b) + +`internal/daemon/host_directory.go` groups directory listing, creation and native +folder selection in the existing daemon package. `host.go` now contains 176 +lines of host RPC dispatch and attention aggregation. This makes filesystem and +platform picker behavior independently findable without a new service or +interface. Callers and tests stay unchanged. + +The Go AST-directed extraction moved exactly `hostDirectories`, +`hostDirectoryCreate`, `directoryPickCommand`, and `hostDirectoryPick`. All six +original function declarations and their comments are byte-identical; the +remaining source is unchanged apart from imports and whitespace. Directory +filtering, bounds, errors, permissions, platform commands and cancellation +behavior therefore retain their original implementation. Three current directory +source references in `docs/features.md` follow the move; theme references still +point to host dispatch. + +Existing host, directory and related RPC race/shuffle tests passed (4.644s), as +did module build, vet and whipvet. The same-package move adds no test or runtime +interface; existing tests remain in place. The full daemon suite was not repeated +locally for this byte-identical same-package move; all required hosted jobs +remain enabled. + +Fresh compatibility evidence at +`/private/tmp/whip-reorg-04b-compat-evidence/evidence.json` passed against fixed +SDK/reference `271c0f8d2a35648d1b45056d57432590b783483c` and immediate parent +`13493cf20dd84c7c97a18d33b1a6202d849eae94`, using Go 1.27.0 darwin/arm64 and +Node 24.14.1. All four changed files, including the new Go file, were staged +before the guard captured `candidateDiff`; its precommit `candidateRevision` +is the parent. Subsequent changes only correct a documentation source reference +and record these results; production source matches the tested candidate. + +Fresh fixed, parent and candidate binaries passed both transport transcript +comparisons, deliberate response/event-order mutation rejection, lifecycle +checks and fixed/immediate-base rollback covering both engines, retained +root/child state, content, schema and trace/export. The candidate binary SHA-256 +is `7f2bff23200cb61ecdb73b4939ca643cc8064a2212ae89421c67b3a66a48e85f`. diff --git a/docs/features.md b/docs/features.md index 21aa71c1a..11df8811b 100644 --- a/docs/features.md +++ b/docs/features.md @@ -815,9 +815,9 @@ behavior to its owning code and repeatable validation. | Behavior | Implementation | Validation | | --- | --- | --- | | Live session trace view (resizable execution tree, waterfall, and span details; pointer/keyboard dividers; ~30 fps live clock, paused when hidden/idle or motion is reduced) fed by durable nanosecond spans and live span events; one trace per root turn with child turns parented under their cause; OTLP/JSON export with GenAI + OpenInference attributes via `trace.export` and `whipcode sessions export` | `internal/session/{span,otlp_export}.go`, `internal/daemon/spans.go`, `packages/sdk/src/trace.ts`, `packages/app/src/{trace-view,trace-math}.ts*`, `cmd/whip/sessions_export.go` | `internal/session/{span,otlp_export}_test.go`, `internal/daemon/v2_event_schema_test.go`, `packages/sdk/test/trace.test.ts`, `packages/app/test/{trace-view,trace-math}.test.ts*` | -| Attach to existing hosts, discover each directory tree, and route to retained sessions | `apps/web/src/main.tsx`, `packages/app/src/runtime.ts`, `packages/app/src/{shell,directory-picker}.tsx`, `internal/daemon/host.go` | `packages/app/test/runtime.test.ts`, `internal/daemon/host_test.go`, `apps/web/scripts/browser.mjs` | -| Choose a Local working directory in the OS-native folder dialog (osascript/zenity/kdialog/PowerShell), falling back to the web directory browser; Remote uses its daemon directory browser | `host.directory.pick` in `internal/{protocol,daemon}/host.go`, `packages/sdk/src/services.ts`, `packages/app/src/directory-picker.tsx` | `TestDirectoryPickCommand`/`TestHostDirectoryPickValidation` in `internal/daemon/host_test.go` | -| Create a folder while choosing a new-session directory: native desktop New Folder, or inline New folder on the selected host; validate one child name, preserve errors, open the created folder, then explicitly Choose folder. Older hosts retain browsing with an update explanation. | `apps/desktop/src/native.ts`, `host.directory.create` in `internal/{protocol,daemon}/host.go`, `packages/sdk/src/services.ts`, `packages/app/src/remote-directory-dialog.tsx` | `apps/desktop/tests/native.test.ts`, `internal/daemon/host_test.go`, `packages/sdk/test/services.test.ts`, `packages/app/test/remote-directory-dialog.test.tsx` | +| Attach to existing hosts, discover each directory tree, and route to retained sessions | `apps/web/src/main.tsx`, `packages/app/src/runtime.ts`, `packages/app/src/{shell,directory-picker}.tsx`, `internal/daemon/{host,host_directory}.go` | `packages/app/test/runtime.test.ts`, `internal/daemon/host_test.go`, `apps/web/scripts/browser.mjs` | +| Choose a Local working directory in the OS-native folder dialog (osascript/zenity/kdialog/PowerShell), falling back to the web directory browser; Remote uses its daemon directory browser | `host.directory.pick` in `internal/protocol/host.go` and `internal/daemon/host_directory.go`, `packages/sdk/src/services.ts`, `packages/app/src/directory-picker.tsx` | `TestDirectoryPickCommand`/`TestHostDirectoryPickValidation` in `internal/daemon/host_test.go` | +| Create a folder while choosing a new-session directory: native desktop New Folder, or inline New folder on the selected host; validate one child name, preserve errors, open the created folder, then explicitly Choose folder. Older hosts retain browsing with an update explanation. | `apps/desktop/src/native.ts`, `host.directory.create` in `internal/protocol/host.go` and `internal/daemon/host_directory.go`, `packages/sdk/src/services.ts`, `packages/app/src/remote-directory-dialog.tsx` | `apps/desktop/tests/native.test.ts`, `internal/daemon/host_test.go`, `packages/sdk/test/services.test.ts`, `packages/app/test/remote-directory-dialog.test.tsx` | | Multiple daemon connections, Local-owned saved profiles, verified identities, isolated disconnects and guided Local/Remote session creation | `packages/app/src/{hosts,runtime}.ts`, `{host-dialog,welcome,settings}.tsx`, `internal/config/remote_hosts.go`, daemon configuration service | `packages/app/test/hosts.test.ts`, `runtime.test.ts`, `sidebar-creation.test.tsx`; `internal/config/remote_hosts_test.go`; `TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts` | | Search and advisory attention across hosts, source labels/filter, independent bounded pagination and partial failures without root hydration | `packages/app/src/{session-search-dialog,attention}.tsx` | `packages/app/test/multi-host-discovery.test.tsx` | | Author data-only agent definitions in Settings (persona, rules, discovery, modules, capabilities, surface), copy built-ins, add revisions to registered ids, and pick the agent a new session runs | `packages/app/src/settings/agents.tsx`, `packages/app/src/definitions.ts`, `packages/app/src/welcome.tsx`, `session-tabs.ts` (`definition`) | `packages/app/test/settings-agents.test.tsx`, `sidebar-creation.test.tsx` (agent picker), `session-tabs.test.ts` | diff --git a/internal/daemon/host.go b/internal/daemon/host.go index c745987f9..431f873a8 100644 --- a/internal/daemon/host.go +++ b/internal/daemon/host.go @@ -4,16 +4,8 @@ import ( "context" "encoding/json" "errors" - "fmt" - "io" - "io/fs" - "os" - "os/exec" "path/filepath" - "runtime" "slices" - "strconv" - "strings" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/protocol" @@ -108,173 +100,6 @@ func (s *Server) handleHost(ctx context.Context, request rpcMessage) (any, *RPCE return result, rpcFromError(err), true } -func hostDirectories(ctx context.Context, p protocol.HostDirectoryParams) (protocol.HostDirectoryResult, error) { - result := protocol.HostDirectoryResult{Entries: []protocol.HostDirectoryEntry{}} - if p.Limit < 1 || p.Limit > 128 || len(p.Path) > 4096 || len(p.Prefix) > 256 || len(p.After) > 256 || strings.ContainsAny(p.Prefix+p.After, `/\`+"\x00") { - return result, rpcFailure(-32602, "directories require limit 1..128, path up to 4096 bytes, and filename filters up to 256 bytes") - } - path := p.Path - if path == "" || path == "~" || strings.HasPrefix(path, "~/") { - home, err := os.UserHomeDir() - if err != nil { - return result, err - } - path = filepath.Join(home, strings.TrimPrefix(path, "~/")) - if p.Path == "" || p.Path == "~" { - path = home - } - } - if !filepath.IsAbs(path) { - return result, rpcFailure(-32602, "directory path must be absolute or start with ~/") - } - result.Path, result.Parent = filepath.Clean(path), filepath.Dir(filepath.Clean(path)) - file, err := os.Open(path) //nolint:gosec // G304: the host directory picker intentionally lists the user-requested absolute directory - if err != nil { - return result, err - } - defer func() { _ = file.Close() }() - entries := []fs.DirEntry{} - for len(entries) < 20000 { - if err := ctx.Err(); err != nil { - return result, err - } - batch, err := file.ReadDir(min(128, 20000-len(entries))) - entries = append(entries, batch...) - if errors.Is(err, io.EOF) { - break - } - if err != nil { - return result, err - } - } - result.Truncated = len(entries) == 20000 - slices.SortFunc(entries, func(a, b fs.DirEntry) int { return strings.Compare(a.Name(), b.Name()) }) - bytes := len(result.Path) + len(result.Parent) - for _, entry := range entries { - if err := ctx.Err(); err != nil { - return result, err - } - if entry.Name() <= p.After || !strings.HasPrefix(entry.Name(), p.Prefix) || !p.ShowHidden && strings.HasPrefix(entry.Name(), ".") { - continue - } - child := filepath.Join(result.Path, entry.Name()) - isDir := entry.IsDir() - if entry.Type()&os.ModeSymlink != 0 { - if info, err := os.Stat(child); err == nil { - isDir = info.IsDir() - } - } - if !isDir { - continue - } - // JSON may escape every input byte; reserve worst-case encoded space. - bytes += 6*(len(child)+len(entry.Name())) + 128 - if len(result.Entries) == p.Limit || bytes > 384<<10 { - result.HasMore = true - break - } - result.Entries = append(result.Entries, protocol.HostDirectoryEntry{Name: entry.Name(), Path: child}) - } - if result.HasMore && len(result.Entries) > 0 { - result.NextAfter = result.Entries[len(result.Entries)-1].Name - } - return result, nil -} - -func hostDirectoryCreate(ctx context.Context, p protocol.HostDirectoryCreateParams) (protocol.HostDirectoryCreateResult, error) { - result := protocol.HostDirectoryCreateResult{} - if len(p.Parent) > 4096 || strings.ContainsRune(p.Parent, 0) || !filepath.IsAbs(p.Parent) { - return result, rpcFailure(-32602, "parent must be an absolute directory path of at most 4096 bytes") - } - if strings.TrimSpace(p.Name) == "" || len(p.Name) > 255 || p.Name == "." || p.Name == ".." || - strings.ContainsAny(p.Name, "/\\\x00") || !filepath.IsLocal(p.Name) { - return result, rpcFailure(-32602, "folder name must be one nonblank component of at most 255 bytes, without separators, NUL, dot or dot-dot") - } - // Windows otherwise normalizes trailing dots/spaces and accepts alternate streams. - if runtime.GOOS == "windows" && (strings.ContainsAny(p.Name, `<>:"|?*`) || - strings.HasSuffix(p.Name, ".") || strings.HasSuffix(p.Name, " ") || - strings.ContainsFunc(p.Name, func(r rune) bool { return r < 32 })) { - return result, rpcFailure(-32602, "folder name contains characters or aliases that are invalid on Windows") - } - if err := ctx.Err(); err != nil { - return result, err - } - path := filepath.Join(p.Parent, p.Name) - // The trusted host picker intentionally creates only one user-requested directory. - if err := os.Mkdir(path, 0o700); err != nil { - return result, fmt.Errorf("create folder: %w", err) - } - result.Path = path - return result, nil -} - -// directoryPickCommand returns the native folder-chooser invocation for goos -// (osascript on darwin, zenity or kdialog on linux, PowerShell Forms on -// windows) and a predicate mapping a failure to a user cancellation. -func directoryPickCommand(goos, start string) (name string, args []string, cancelled func(output string) bool) { - switch goos { - case "darwin": - script := `choose folder with prompt "Choose a working directory"` - if start != "" { - script += ` default location (POSIX file ` + strconv.Quote(start) + `)` - } - return "osascript", []string{"-e", `POSIX path of (` + script + `)`}, - func(output string) bool { return strings.Contains(output, "User canceled") } - case "linux": - if path, err := exec.LookPath("zenity"); err == nil { - return path, []string{"--file-selection", "--directory", "--title=Choose a working directory"}, - func(output string) bool { return true } // zenity exits 1 only on cancel - } - if path, err := exec.LookPath("kdialog"); err == nil { - args := []string{"--getexistingdirectory"} - if start != "" { - args = append(args, start) - } - return path, args, func(output string) bool { return true } - } - case "windows": - // `4` is the SSF_DESKTOPDIRECTORY folder constant (numeric so quoting is moot). - return "powershell", []string{ - "-NoProfile", "-NonInteractive", "-Command", - `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.FolderBrowserDialog; $d.Description = 'Choose a working directory'; $d.RootFolder = 4; if ($d.ShowDialog() -eq 'OK') { $d.SelectedPath }`, - }, - func(output string) bool { return output == "" } // cancel prints no path - } - return "", nil, nil -} - -// hostDirectoryPick opens the OS-native folder chooser on the execution -// machine. Only available where the daemon itself has a desktop session; a -// headless daemon (SSH, container, no zenity/kdialog) errors so the browser -// falls back to the web directory browser. -func hostDirectoryPick(ctx context.Context, p protocol.HostDirectoryPickParams) (protocol.HostDirectoryPickResult, error) { - result := protocol.HostDirectoryPickResult{} - if len(p.Start) > 4096 || (p.Start != "" && !filepath.IsAbs(p.Start)) { - return result, rpcFailure(-32602, "directory pick requires an absolute start path of at most 4096 bytes") - } - name, args, cancelled := directoryPickCommand(runtime.GOOS, filepath.Clean(p.Start)) - if name == "" { - return result, fmt.Errorf("no native folder picker available on %s", runtime.GOOS) - } - var stdout, stderr strings.Builder - cmd := exec.CommandContext(ctx, name, args...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - output := strings.TrimSpace(stdout.String()) - if err != nil { - if cancelled != nil && cancelled(output+stderr.String()) { - return protocol.HostDirectoryPickResult{Cancelled: true}, nil - } - return result, fmt.Errorf("folder picker failed: %w: %s", err, strings.TrimSpace(stderr.String())) - } - if output == "" || len(output) > 4096 { - return result, fmt.Errorf("folder picker returned no usable path: %s", strings.TrimSpace(stderr.String())) - } - result.Path = strings.TrimRight(output, `/\`) - return result, nil -} - func (s *Server) hostAttention(ctx context.Context, p protocol.HostAttentionParams) (protocol.HostAttentionResult, error) { result := protocol.HostAttentionResult{Items: []protocol.HostAttentionItem{}} if p.Limit < 1 || p.Limit > 128 || p.MaxBytes < 4096 || p.MaxBytes > 512<<10 || len(p.AfterID) > 256 { diff --git a/internal/daemon/host_directory.go b/internal/daemon/host_directory.go new file mode 100644 index 000000000..5a4486426 --- /dev/null +++ b/internal/daemon/host_directory.go @@ -0,0 +1,185 @@ +package daemon + +import ( + "context" + "errors" + "fmt" + "io" + "io/fs" + "os" + "os/exec" + "path/filepath" + "runtime" + "slices" + "strconv" + "strings" + + "github.com/context-labs/whip/internal/protocol" +) + +func hostDirectories(ctx context.Context, p protocol.HostDirectoryParams) (protocol.HostDirectoryResult, error) { + result := protocol.HostDirectoryResult{Entries: []protocol.HostDirectoryEntry{}} + if p.Limit < 1 || p.Limit > 128 || len(p.Path) > 4096 || len(p.Prefix) > 256 || len(p.After) > 256 || strings.ContainsAny(p.Prefix+p.After, `/\`+"\x00") { + return result, rpcFailure(-32602, "directories require limit 1..128, path up to 4096 bytes, and filename filters up to 256 bytes") + } + path := p.Path + if path == "" || path == "~" || strings.HasPrefix(path, "~/") { + home, err := os.UserHomeDir() + if err != nil { + return result, err + } + path = filepath.Join(home, strings.TrimPrefix(path, "~/")) + if p.Path == "" || p.Path == "~" { + path = home + } + } + if !filepath.IsAbs(path) { + return result, rpcFailure(-32602, "directory path must be absolute or start with ~/") + } + result.Path, result.Parent = filepath.Clean(path), filepath.Dir(filepath.Clean(path)) + file, err := os.Open(path) //nolint:gosec // G304: the host directory picker intentionally lists the user-requested absolute directory + if err != nil { + return result, err + } + defer func() { _ = file.Close() }() + entries := []fs.DirEntry{} + for len(entries) < 20000 { + if err := ctx.Err(); err != nil { + return result, err + } + batch, err := file.ReadDir(min(128, 20000-len(entries))) + entries = append(entries, batch...) + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return result, err + } + } + result.Truncated = len(entries) == 20000 + slices.SortFunc(entries, func(a, b fs.DirEntry) int { return strings.Compare(a.Name(), b.Name()) }) + bytes := len(result.Path) + len(result.Parent) + for _, entry := range entries { + if err := ctx.Err(); err != nil { + return result, err + } + if entry.Name() <= p.After || !strings.HasPrefix(entry.Name(), p.Prefix) || !p.ShowHidden && strings.HasPrefix(entry.Name(), ".") { + continue + } + child := filepath.Join(result.Path, entry.Name()) + isDir := entry.IsDir() + if entry.Type()&os.ModeSymlink != 0 { + if info, err := os.Stat(child); err == nil { + isDir = info.IsDir() + } + } + if !isDir { + continue + } + // JSON may escape every input byte; reserve worst-case encoded space. + bytes += 6*(len(child)+len(entry.Name())) + 128 + if len(result.Entries) == p.Limit || bytes > 384<<10 { + result.HasMore = true + break + } + result.Entries = append(result.Entries, protocol.HostDirectoryEntry{Name: entry.Name(), Path: child}) + } + if result.HasMore && len(result.Entries) > 0 { + result.NextAfter = result.Entries[len(result.Entries)-1].Name + } + return result, nil +} + +func hostDirectoryCreate(ctx context.Context, p protocol.HostDirectoryCreateParams) (protocol.HostDirectoryCreateResult, error) { + result := protocol.HostDirectoryCreateResult{} + if len(p.Parent) > 4096 || strings.ContainsRune(p.Parent, 0) || !filepath.IsAbs(p.Parent) { + return result, rpcFailure(-32602, "parent must be an absolute directory path of at most 4096 bytes") + } + if strings.TrimSpace(p.Name) == "" || len(p.Name) > 255 || p.Name == "." || p.Name == ".." || + strings.ContainsAny(p.Name, "/\\\x00") || !filepath.IsLocal(p.Name) { + return result, rpcFailure(-32602, "folder name must be one nonblank component of at most 255 bytes, without separators, NUL, dot or dot-dot") + } + // Windows otherwise normalizes trailing dots/spaces and accepts alternate streams. + if runtime.GOOS == "windows" && (strings.ContainsAny(p.Name, `<>:"|?*`) || + strings.HasSuffix(p.Name, ".") || strings.HasSuffix(p.Name, " ") || + strings.ContainsFunc(p.Name, func(r rune) bool { return r < 32 })) { + return result, rpcFailure(-32602, "folder name contains characters or aliases that are invalid on Windows") + } + if err := ctx.Err(); err != nil { + return result, err + } + path := filepath.Join(p.Parent, p.Name) + // The trusted host picker intentionally creates only one user-requested directory. + if err := os.Mkdir(path, 0o700); err != nil { + return result, fmt.Errorf("create folder: %w", err) + } + result.Path = path + return result, nil +} + +// directoryPickCommand returns the native folder-chooser invocation for goos +// (osascript on darwin, zenity or kdialog on linux, PowerShell Forms on +// windows) and a predicate mapping a failure to a user cancellation. +func directoryPickCommand(goos, start string) (name string, args []string, cancelled func(output string) bool) { + switch goos { + case "darwin": + script := `choose folder with prompt "Choose a working directory"` + if start != "" { + script += ` default location (POSIX file ` + strconv.Quote(start) + `)` + } + return "osascript", []string{"-e", `POSIX path of (` + script + `)`}, + func(output string) bool { return strings.Contains(output, "User canceled") } + case "linux": + if path, err := exec.LookPath("zenity"); err == nil { + return path, []string{"--file-selection", "--directory", "--title=Choose a working directory"}, + func(output string) bool { return true } // zenity exits 1 only on cancel + } + if path, err := exec.LookPath("kdialog"); err == nil { + args := []string{"--getexistingdirectory"} + if start != "" { + args = append(args, start) + } + return path, args, func(output string) bool { return true } + } + case "windows": + // `4` is the SSF_DESKTOPDIRECTORY folder constant (numeric so quoting is moot). + return "powershell", []string{ + "-NoProfile", "-NonInteractive", "-Command", + `Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.FolderBrowserDialog; $d.Description = 'Choose a working directory'; $d.RootFolder = 4; if ($d.ShowDialog() -eq 'OK') { $d.SelectedPath }`, + }, + func(output string) bool { return output == "" } // cancel prints no path + } + return "", nil, nil +} + +// hostDirectoryPick opens the OS-native folder chooser on the execution +// machine. Only available where the daemon itself has a desktop session; a +// headless daemon (SSH, container, no zenity/kdialog) errors so the browser +// falls back to the web directory browser. +func hostDirectoryPick(ctx context.Context, p protocol.HostDirectoryPickParams) (protocol.HostDirectoryPickResult, error) { + result := protocol.HostDirectoryPickResult{} + if len(p.Start) > 4096 || (p.Start != "" && !filepath.IsAbs(p.Start)) { + return result, rpcFailure(-32602, "directory pick requires an absolute start path of at most 4096 bytes") + } + name, args, cancelled := directoryPickCommand(runtime.GOOS, filepath.Clean(p.Start)) + if name == "" { + return result, fmt.Errorf("no native folder picker available on %s", runtime.GOOS) + } + var stdout, stderr strings.Builder + cmd := exec.CommandContext(ctx, name, args...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err := cmd.Run() + output := strings.TrimSpace(stdout.String()) + if err != nil { + if cancelled != nil && cancelled(output+stderr.String()) { + return protocol.HostDirectoryPickResult{Cancelled: true}, nil + } + return result, fmt.Errorf("folder picker failed: %w: %s", err, strings.TrimSpace(stderr.String())) + } + if output == "" || len(output) > 4096 { + return result, fmt.Errorf("folder picker returned no usable path: %s", strings.TrimSpace(stderr.String())) + } + result.Path = strings.TrimRight(output, `/\`) + return result, nil +} From 62e6754795a15f6b67cd7723d6027ca7d84813a5 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:05:47 -0700 Subject: [PATCH 37/67] test(daemon): characterize process manager ownership --- .../daemon/daemon_process_ownership_test.go | 236 ++++++++++++++++++ internal/daemon/recursive_runtime_test.go | 10 +- internal/daemon/session_test.go | 3 + 3 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 internal/daemon/daemon_process_ownership_test.go diff --git a/internal/daemon/daemon_process_ownership_test.go b/internal/daemon/daemon_process_ownership_test.go new file mode 100644 index 000000000..7a940fa74 --- /dev/null +++ b/internal/daemon/daemon_process_ownership_test.go @@ -0,0 +1,236 @@ +package daemon + +import ( + "context" + "database/sql" + "errors" + "fmt" + "path/filepath" + "slices" + "strings" + "sync/atomic" + "testing" + + "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/session" + "github.com/context-labs/whip/internal/tools" +) + +func TestDaemonProcessEnvironmentSnapshotsBeforeConstruction(t *testing.T) { + const variable = "LC_WHIP_PROCESS_OWNERSHIP" + t.Setenv(variable, "at-store-open") + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + processes := store.Processes() + defer store.Close() + rootID := createRoot(t, store) + t.Setenv(variable, "before-daemon-new") + services := tools.NewServices() + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: NewToolRunner(services)}, nil + }) + if err != nil { + t.Fatal(err) + } + defer owner.Close() + t.Setenv(variable, "before-root-bind") + if _, err := owner.Open(rootID); err != nil { + t.Fatal(err) + } + options := services.ProcessOptions() + if options.Processes != processes || options.RootID != rootID { + t.Fatalf("borrowed process scope = %p %q, want %p %q", options.Processes, options.RootID, processes, rootID) + } + environment, err := options.Processes.ChildEnvironment(nil) + if err != nil { + t.Fatal(err) + } + if !slices.Contains(environment, variable+"=at-store-open") { + t.Fatal("process environment was not captured before daemon construction") + } + if err := owner.Close(); err != nil { + t.Fatal(err) + } +} + +func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { + path := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, path) + defer store.Close() + processes := store.Processes() + rootID := createRoot(t, store) + if err := store.SetBudgetLimit(t.Context(), rootID, "", session.BudgetTokens, 100); err != nil { + t.Fatal(err) + } + fixtureDB, err := sql.Open("sqlite", path) + if err != nil { + t.Fatal(err) + } + defer fixtureDB.Close() + const marker = "fixture process recovery failure" + if _, err := fixtureDB.Exec(`CREATE TRIGGER reject_process_ownership_recovery BEFORE UPDATE ON budgets BEGIN SELECT RAISE(ABORT,'fixture process recovery failure'); END`); err != nil { + t.Fatal(err) + } + defer fixtureDB.Exec(`DROP TRIGGER IF EXISTS reject_process_ownership_recovery`) + var stopped atomic.Int32 + if _, err := processes.RegisterStop(rootID, func() error { stopped.Add(1); return nil }); err != nil { + t.Fatal(err) + } + factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + } + owner, err := New(store, factory) + if owner != nil || err == nil || !strings.Contains(err.Error(), marker) { + t.Fatalf("recovery result = %v, %v", owner, err) + } + if stopped.Load() != 0 { + t.Fatal("failed construction closed caller-owned processes") + } + if _, err := store.LoadMeta(rootID); err != nil { + t.Fatalf("failed construction closed caller-owned database: %v", err) + } + unregister, err := processes.RegisterStop("after-failed-new", func() error { return nil }) + if err != nil { + t.Fatalf("failed construction closed caller-owned manager: %v", err) + } + unregister() + if !store.AcquireDaemon() { + t.Fatal("failed recovery retained the daemon ownership guard") + } + store.ReleaseDaemon() + if _, err := fixtureDB.Exec(`DROP TRIGGER reject_process_ownership_recovery`); err != nil { + t.Fatal(err) + } + owner, err = New(store, factory) + if err != nil { + t.Fatalf("retry with the same resources: %v", err) + } + defer owner.Close() + if err := owner.Close(); err != nil { + t.Fatal(err) + } + if stopped.Load() != 1 { + t.Fatalf("successful owner's shutdown callbacks = %d, want 1", stopped.Load()) + } +} + +func TestDaemonCloseStopsProcessesBeforeStoreAndCachesErrors(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + defer store.Close() + processes := store.Processes() + rootID := createRoot(t, store) + owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + }) + if err != nil { + t.Fatal(err) + } + defer owner.Close() + sentinels := []error{errors.New("first process stop"), errors.New("second process stop")} + counts := make([]int, len(sentinels)) + databaseErrors := make([]error, len(sentinels)) + for i, sentinel := range sentinels { + // Unopened scopes reach global Close rather than an actor's StopRoot. + if _, err := processes.RegisterStop(fmt.Sprintf("unopened-%d", i), func() error { + counts[i]++ + _, loadErr := store.LoadMeta(rootID) + databaseErrors[i] = errors.Join(loadErr, store.SetGoal(rootID, "written during process stop")) + return sentinel + }); err != nil { + t.Fatal(err) + } + } + first := owner.Close() + for i, sentinel := range sentinels { + if counts[i] != 1 || databaseErrors[i] != nil || !errors.Is(first, sentinel) { + t.Fatalf("callback %d: count=%d database=%v close=%v", i, counts[i], databaseErrors[i], first) + } + } + if _, err := processes.RegisterStop("after-close", func() error { return nil }); !errors.Is(err, capability.ErrProcessManagerClosed) { + t.Fatalf("manager after close = %v", err) + } + if _, err := store.LoadMeta(rootID); err == nil { + t.Fatal("database remained open after daemon shutdown") + } + if repeated := owner.Close(); repeated != first { + t.Fatalf("Close did not return the cached error: first=%v repeated=%v", first, repeated) + } + for i, count := range counts { + if count != 1 { + t.Fatalf("callback %d repeated: %d", i, count) + } + } + if !store.AcquireDaemon() { + t.Fatal("Close retained the daemon ownership guard") + } + store.ReleaseDaemon() +} + +func TestFailedRootBindStopsOnlyItsProcessScope(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + defer store.Close() + processes := store.Processes() + healthyID, failingID := createRoot(t, store), createRoot(t, store) + bindErr := errors.New("fixture root bind failure") + var healthyStops, failingStops atomic.Int32 + owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + services := tools.NewServices() + return Components{Runner: NewToolRunner(services), Bind: func(context.Context, *Session) error { + options := services.ProcessOptions() + if options.Processes != processes || options.RootID != meta.ID { + return fmt.Errorf("borrowed process scope = %p %q, want %p %q", options.Processes, options.RootID, processes, meta.ID) + } + count := &healthyStops + if meta.ID == failingID { + count = &failingStops + } + if _, err := options.Processes.RegisterStop(meta.ID, func() error { count.Add(1); return nil }); err != nil { + return err + } + if meta.ID == failingID { + return bindErr + } + return nil + }}, nil + }) + if err != nil { + t.Fatal(err) + } + defer owner.Close() + healthy, err := owner.Open(healthyID) + if err != nil { + t.Fatal(err) + } + if _, err := owner.Open(failingID); !errors.Is(err, bindErr) { + t.Fatalf("failed root bind = %v", err) + } + if failingStops.Load() != 1 || healthyStops.Load() != 0 { + t.Fatalf("partial-bind callbacks: failing=%d healthy=%d", failingStops.Load(), healthyStops.Load()) + } + select { + case <-healthy.Done(): + t.Fatal("failed binding stopped the healthy root") + default: + } + // StopRoot releases only this scope and permits later reactivation. + unregister, err := processes.RegisterStop(failingID, func() error { return nil }) + if err != nil { + t.Fatalf("reactivate failed root scope: %v", err) + } + unregister() + healthy.Stop() + if healthyStops.Load() != 1 || failingStops.Load() != 1 { + t.Fatalf("root stop callbacks: failing=%d healthy=%d", failingStops.Load(), healthyStops.Load()) + } + unregister, err = processes.RegisterStop("after-root-stop", func() error { return nil }) + if err != nil { + t.Fatalf("root stop closed the global manager: %v", err) + } + unregister() + if err := owner.Close(); err != nil { + t.Fatal(err) + } + if _, err := processes.RegisterStop("after-owner-close", func() error { return nil }); !errors.Is(err, capability.ErrProcessManagerClosed) { + t.Fatalf("owner shutdown did not close manager: %v", err) + } +} diff --git a/internal/daemon/recursive_runtime_test.go b/internal/daemon/recursive_runtime_test.go index dd008fb9f..35cd02a19 100644 --- a/internal/daemon/recursive_runtime_test.go +++ b/internal/daemon/recursive_runtime_test.go @@ -94,7 +94,7 @@ func TestRecursiveRuntimeUsesOneInterfaceAtEveryDepth(t *testing.T) { streamText(w, "done") })) defer server.Close() - _, root, runtime := openRecursiveRuntime(t, llm.New(server.URL, "key"), 4) + store, root, runtime := openRecursiveRuntime(t, llm.New(server.URL, "key"), 4) runs := &sync.Map{} runtime.setRunTurnHook(observeRunTurn(runs)) receipt, err := root.Submit(t.Context(), "root work") @@ -124,6 +124,9 @@ func TestRecursiveRuntimeUsesOneInterfaceAtEveryDepth(t *testing.T) { waitAgentIdle(t, child) for _, node := range []*AgentSession{runtime.rootNode, child, grandchild} { + if options := node.agent.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != root.ID() { + t.Fatalf("agent %q process scope = %p %q", node.name, options.Processes, options.RootID) + } all := node.agent.AllTools() if len(all) != 1 || all[0].Def.Function.Name != "rlm_exec" { t.Fatalf("agent %q tools = %#v", node.name, all) @@ -523,6 +526,11 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { if restored == nil { t.Fatalf("retained child %q was not restored", childID) } + for _, node := range []*AgentSession{second.rootNode, restored} { + if options := node.agent.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != secondRoot.ID() { + t.Fatalf("restored agent %q process scope = %p %q", node.name, options.Processes, options.RootID) + } + } if all := restored.agent.AllTools(); len(all) != 1 || all[0].Def.Function.Name != "rlm_exec" { t.Fatalf("restored tools = %#v", all) } diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index d96758b7b..309fd6696 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -883,6 +883,9 @@ func TestOpenBindsMCPProcesses(t *testing.T) { if manager.processes != store.Processes() || manager.rootID != rootID || manager.cwd != root.WorkingDirectory() { t.Fatalf("MCP process scope=%p %q %q", manager.processes, manager.rootID, manager.cwd) } + if options := ag.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != rootID { + t.Fatalf("agent process scope = %p %q", options.Processes, options.RootID) + } if len(ag.AllTools()) != 0 { t.Fatal("MCP process setup changed the model-facing tool surface") } From 8dabac820687fa8dcd0fd1f5e26b059d4e623a4e Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:06:53 -0700 Subject: [PATCH 38/67] test(daemon): preserve resources after duplicate ownership rejection --- internal/daemon/session_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index 309fd6696..52011c67d 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -1382,6 +1382,14 @@ func TestNewRejectsSecondDaemonOwner(t *testing.T) { if _, err := New(store, factory); err == nil || !strings.Contains(err.Error(), "already has a daemon owner") { t.Fatalf("second daemon error=%v", err) } + if _, err := store.LoadMeta(createRoot(t, store)); err != nil { + t.Fatalf("second-owner rejection closed the database: %v", err) + } + unregister, err := store.Processes().RegisterStop("after-second-owner-rejection", func() error { return nil }) + if err != nil { + t.Fatalf("second-owner rejection closed the process manager: %v", err) + } + unregister() } func TestClosePreservesClaimedScheduleWake(t *testing.T) { From 057edb919da1a652fb284e2d54d4cf020a7867c6 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:19:42 -0700 Subject: [PATCH 39/67] refactor(daemon): own shared process lifecycle explicitly --- cmd/whip/daemon.go | 6 +- docs/backend-reorganization-plan.md | 70 +++++++++- internal/agent/authority_test.go | 6 +- internal/daemon/acceptance_test.go | 3 +- internal/daemon/actor_control_test.go | 3 +- internal/daemon/agent_session.go | 2 +- internal/daemon/architecture_test.go | 19 +++ internal/daemon/autostart_test.go | 5 +- internal/daemon/browser_provider_test.go | 6 +- internal/daemon/budget_test.go | 18 ++- internal/daemon/cancel_command_test.go | 3 +- internal/daemon/child_commit_test.go | 3 +- internal/daemon/client_admission_test.go | 6 +- .../daemon/client_control_archive_test.go | 6 +- .../daemon/client_control_behavior_test.go | 6 +- .../daemon/client_control_boundaries_test.go | 6 +- .../daemon/client_control_compaction_test.go | 3 +- internal/daemon/client_control_test.go | 70 ++++++---- internal/daemon/command_test.go | 3 +- internal/daemon/control_test.go | 6 +- internal/daemon/daemon.go | 21 +-- .../daemon/daemon_process_ownership_test.go | 70 ++++++++-- internal/daemon/daemon_test.go | 6 +- internal/daemon/definition_test.go | 3 +- internal/daemon/effort_vocabulary_test.go | 6 +- internal/daemon/execution_engine_test.go | 3 +- internal/daemon/host_test.go | 3 +- internal/daemon/identity_test.go | 12 +- internal/daemon/inbox_queue_test.go | 3 +- internal/daemon/input_lifecycle_test.go | 12 +- internal/daemon/interactive_test.go | 3 +- internal/daemon/mailbox_delivery_test.go | 7 +- internal/daemon/manual_compaction_test.go | 7 +- internal/daemon/mcp_import_service_test.go | 3 +- internal/daemon/metadata_routing_test.go | 6 +- .../model_accounting_acceptance_test.go | 3 +- internal/daemon/model_admission_lock_test.go | 3 +- internal/daemon/permission_mode_test.go | 10 +- internal/daemon/permission_test.go | 12 +- internal/daemon/prompt_test.go | 3 +- .../daemon/provider_client_behavior_test.go | 3 +- internal/daemon/provider_default_test.go | 6 +- internal/daemon/question_snapshot_test.go | 3 +- internal/daemon/recursive_runtime.go | 4 +- internal/daemon/recursive_runtime_test.go | 18 ++- internal/daemon/report_restore_test.go | 3 +- internal/daemon/restart_test.go | 11 +- internal/daemon/root_client_test.go | 3 +- internal/daemon/runtime_parity_test.go | 3 +- internal/daemon/scheduler_test.go | 3 +- internal/daemon/server_test.go | 45 +++++-- internal/daemon/session.go | 7 +- internal/daemon/session_metadata_test.go | 3 +- .../daemon/session_state_ownership_test.go | 6 +- internal/daemon/session_summaries_test.go | 3 +- internal/daemon/session_test.go | 123 ++++++++++++------ internal/daemon/state_test.go | 9 +- internal/daemon/subscription_runtime_test.go | 3 +- internal/daemon/terminal_rpc_test.go | 3 +- internal/daemon/title_lifecycle_test.go | 3 +- internal/daemon/title_notifications_test.go | 6 +- internal/daemon/tool_runner.go | 2 +- internal/daemon/tools_test.go | 3 +- internal/daemon/trace_rpc_test.go | 6 +- internal/daemon/v2_acceptance_test.go | 3 +- internal/daemon/v2_crash_test.go | 3 +- internal/daemon/v2_sdk_test.go | 5 +- internal/daemon/workspace_test.go | 8 +- internal/mcp/serve_test.go | 5 +- internal/session/capability.go | 2 - internal/session/capability_test.go | 3 - internal/session/session.go | 5 +- .../tools/browser_desktop_boundaries_test.go | 2 +- internal/tools/browser_desktop_test.go | 7 +- internal/tools/dispatcher_test.go | 18 ++- internal/tools/jobs_test.go | 5 +- internal/tools/mcp_permission_test.go | 5 +- internal/tools/mcp_test.go | 19 ++- internal/tools/permission_test.go | 5 +- internal/tools/tools_test.go | 3 +- internal/tui/client_integration_test.go | 5 +- 81 files changed, 595 insertions(+), 233 deletions(-) diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index d13e9791d..29d3487ee 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -13,6 +13,7 @@ import ( "syscall" "github.com/context-labs/whip/internal/buildinfo" + "github.com/context-labs/whip/internal/capability" providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/config" @@ -76,9 +77,11 @@ func runDaemon(ctx context.Context, args []string) error { if err != nil { return err } + processes := capability.NewProcessManager() store.SetGlobalPermissionRules(cfg.Permissions.Allow) generation, err := store.BeginDaemonGeneration(context.Background(), version) if err != nil { + _ = processes.Close() _ = store.Close() return err } @@ -93,8 +96,9 @@ func runDaemon(ctx context.Context, args []string) error { kernels := rlm.NewManager(limits.MaxWorkers) defer kernels.Close() factory := daemonRuntimeFactory(store, providers, kernels, limits) - ownerDaemon, err := daemon.New(store, factory, providers) + ownerDaemon, err := daemon.New(store, processes, factory, providers) if err != nil { + _ = processes.Close() _ = store.Close() return err } diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index b09616806..5b9c54c99 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -668,14 +668,15 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | | Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | | Isolated provider test environment | `a57b5261b6225b64451b0d5b06374f721cb83153`, [PR #301](https://github.com/context-labs/whip/pull/301) | Separate test-only repair prevents inherited provider credentials from changing fixtures. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681286958) and current security passed. | -| Dialog assertion readiness | `722b49321f3cb2a70c8d829911279ffd79caf0a0`, [PR #307](https://github.com/context-labs/whip/pull/307), based on PR #301. | Separate test-only repair waits for sheet focus before scroll assertions. The prior combined head `1882979ad414c256cada7b2fb71e11a02f46bd4e` passed the 36-test workflow-policy suite, [full CI](https://github.com/context-labs/whip/actions/runs/36681287194) and security, including both compatibility jobs and the 90% coverage floor. This repair now precedes the guard; [reordered-head CI](https://github.com/context-labs/whip/actions/runs/36685631006) is pending. | +| Dialog assertion readiness | `722b49321f3cb2a70c8d829911279ffd79caf0a0`, [PR #307](https://github.com/context-labs/whip/pull/307), based on PR #301. | Separate test-only repair waits for sheet focus before scroll assertions. The prior combined head `1882979ad414c256cada7b2fb71e11a02f46bd4e` passed the 36-test workflow-policy suite, [full CI](https://github.com/context-labs/whip/actions/runs/36681287194) and security, including both compatibility jobs and the 90% coverage floor. This repair now precedes the guard; [reordered-head CI](https://github.com/context-labs/whip/actions/runs/36685631006) and [security](https://github.com/context-labs/whip/actions/runs/36685630150) passed. | | Frozen-contract gate | `8f0230444eb447e87c619d7c689eca811ac5d1f3`, [PR #302](https://github.com/context-labs/whip/pull/302), based on PR #307. | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine rollback. At historical head `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [CI](https://github.com/context-labs/whip/actions/runs/36681287828) passed both compatibility jobs, Go coverage, lint and runtime but failed the independently reproduced UI race. The new head includes the separate repair and has the exact previously green combined prerequisite tree. [Fresh CI](https://github.com/context-labs/whip/actions/runs/36686140019) remains pending. | | Host MCP ownership (plan PR 2) | `bfd030fb7bee920982c8d0ab9f6a4820be962166`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The original-implementation cancellation characterization, focused MCP/icon race tests, build/vet/whipvet, full daemon race/shuffle (250.722s), and fixed/immediate-base compatibility passed. Historical head `d8175212d3db3371b14862dc07ad24fc62393108` passed [full CI](https://github.com/context-labs/whip/actions/runs/36682214774) and security. Its tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686146852) is pending. | | Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686153135) is pending. | | Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686160171) is pending. | -| Provider package extraction (plan PR 3b2) | `355b792bc99567068e65fdd0fd9f992a5b50ea0c`, [PR #308](https://github.com/context-labs/whip/pull/308), based on PR #306. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) is pending; security passed. | +| Provider package extraction (plan PR 3b2) | `355b792bc99567068e65fdd0fd9f992a5b50ea0c`, [PR #308](https://github.com/context-labs/whip/pull/308), based on PR #306. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) and [security](https://github.com/context-labs/whip/actions/runs/36685870367) passed. | | Startup factory extraction (plan PR 4a) | `13493cf20dd84c7c97a18d33b1a6202d849eae94`, [PR #309](https://github.com/context-labs/whip/pull/309), based on PR #308. | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. | -| Host directory grouping (plan PR 4b) | `codex/backend-reorg-04b-host-directory`, based on PR #309 (`13493cf20dd84c7c97a18d33b1a6202d849eae94`). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. Hosted checks follow publication. | +| Host directory grouping (plan PR 4b) | `0099a665221ba54ac23ca6656a8a1a017af6f48d`, [PR #310](https://github.com/context-labs/whip/pull/310), based on PR #309 (`13493cf20dd84c7c97a18d33b1a6202d849eae94`). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. | +| Process ownership (plan PR 5) | `codex/backend-reorg-05-process-ownership`, based on PR #310 (`0099a665221ba54ac23ca6656a8a1a017af6f48d`). | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -883,3 +884,66 @@ comparisons, deliberate response/event-order mutation rejection, lifecycle checks and fixed/immediate-base rollback covering both engines, retained root/child state, content, schema and trace/export. The candidate binary SHA-256 is `7f2bff23200cb61ecdb73b4939ca643cc8064a2212ae89421c67b3a66a48e85f`. + + +### Process ownership (plan PR 5) + +The process manager moves from `session.Store` to daemon composition. The +production change touches eight files: startup construction/failure cleanup, +the daemon and root fields/constructors/teardown, existing agent/tool/recursive +borrowers, and removal of the Store field/constructor/accessor. The process +implementation, SQL, schema, provider lifecycle, and client protocol are +unchanged. Workspace ownership remains in storage for the separate next step. + +| Boundary | Owner and lifetime after this change | Preserved behavior | +| --- | --- | --- | +| Construction | `runDaemon` constructs one manager immediately after successful `session.Open`. | Environment snapshot precedes permission rules, daemon generation, provider discovery, kernels, and root factories. | +| Failed startup | Caller closes manager, then Store, after generation or `daemon.New` failure. | Original failure remains the return value; provider/kernel defers retain their existing order. | +| `daemon.New` | Successful construction adopts the supplied Store and manager. Failure adopts neither. | Existing nil Store/factory error has priority; duplicate ownership and recovery failure preserve caller resources; recovery failure releases the Store guard. Nil manager is rejected explicitly after the existing input checks. | +| Borrowers | Every root borrows the same daemon pointer; root/child tool services and MCP retain that pointer and root scope. | No per-root manager, lazy allocation, new registry, or process policy. Standalone MCP probing keeps its independent owner. | +| Root/partial bind teardown | Existing root teardown and failed-open defer call `StopRoot(rootID)`. | Defer placement, component close order, worker joins, settlement, and root isolation are unchanged. Root cleanup does not close the shared manager. | +| Global shutdown | At the old final Store-close point, daemon joins `processes.Close()` then `store.Close()`. | Callbacks can still use the database; sentinel errors remain joined; `sync.Once` caches the same repeated Close result and guard release stays deferred. Root errors are not newly aggregated. | +| Fixtures | Native/tagged fixtures name their manager and pass it explicitly; successful owners close it before fallback test cleanup. | Retry/duplicate constructors reuse a handle; reopened owners receive a fresh one. Direct borrowers close before their manager and database. `openStore` gains no hidden cleanup or runtime resource. | + +Before production edits, four characterizations locked down environment snapshot +timing, live-resource recovery failure and retry, shutdown database usability +with joined/cached errors, and partial-bind/root StopRoot isolation. Existing MCP, +agent, fresh recursive child/grandchild, restored child, and duplicate-owner tests +gained pointer/liveness assertions. The eight focused race cases passed in +4.481s at test-only commit `05eef77e9ff1b8ca6ac2dac4a17994dc594bf59e`. +The same cases plus explicit nil-manager/error-priority and storage-construction +checks passed after the move in 4.493s. No test assertion was weakened to accept +changed runtime behavior; only the obsolete Store-owned process accessor +assertion was removed from storage's accessor test. + +The AST-directed fixture migration and an exact source conservation check cover +all eight changed production files, permitting only the enumerated ownership +edits. All 380 pre-existing test function names in changed files remain. Evidence: +`/private/tmp/whip-pr5-fixtures-transform.log` and +`/private/tmp/whip-pr5-production-proof.log`. + +Local validation passed: full daemon race/shuffle (275.485s), session (148.173s), +capability (30.041s), tools (14.327s), MCP (22.298s), and agent (9.192s) race +suites; full CLI race/shuffle (68.494s); integration-tagged daemon/TUI/CLI fixture +compilation; and module build, vet, and whipvet. Final test-only cleanup-order +adjustments passed focused daemon/tools race runs (2.381s/3.911s). Independent +review caught a restart fixture reusing its old closed manager after direct +`session.Open`; its new lifetime now receives a fresh named manager and an +explicit registration/liveness assertion, which passed with race detection +(2.083s). Production behavior was unchanged by that fixture correction. + +The initial frozen compatibility run against the fixed reference and full PR4b +parent `0099a665221ba54ac23ca6656a8a1a017af6f48d` passed: +`/private/tmp/whip-pr5-compat-evidence/evidence.json`. It covers Unix/WebSocket +responses and ordered events, acceptance/cancellation lifecycle, and both-engine +root/child persisted-data rollback with content, schema, trace pages, and OTLP +export. The final published-parent run will refresh provenance after the +inherited test-header lint correction is rebased through the stack; the current +result records the pre-rebase parent and the initial captured working diff. + +A preflight with CI's golangci-lint 2.13.1 found only the inherited lowercase +provider-header fixture after the new tests adopted explicit SQL contexts and a +narrow explained exception for the required cached-error identity comparison. +Those two fixture cases passed again with race detection (1.916s). The inherited +header correction belongs to PR3b1 and will arrive through the parent rebase; +PR5 does not mix that repair into its ownership change. diff --git a/internal/agent/authority_test.go b/internal/agent/authority_test.go index 22be565c0..8edbe9555 100644 --- a/internal/agent/authority_test.go +++ b/internal/agent/authority_test.go @@ -5,6 +5,7 @@ import ( "path/filepath" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" ) @@ -21,6 +22,9 @@ func bindTestServices(t *testing.T, services *tools.Services, root string) { t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) + t.Cleanup(services.Close) rootID, err := store.Create(session.SessionKindAgent, root, "m", "p") if err != nil { t.Fatal(err) @@ -30,7 +34,7 @@ func bindTestServices(t *testing.T, services *tools.Services, root string) { t.Fatal(err) } services.SetProcessMarkers(rootID, "m") - if err := services.BindDispatcher(store, store.Workspaces(), store.Processes(), authority); err != nil { + if err := services.BindDispatcher(store, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } } diff --git a/internal/daemon/acceptance_test.go b/internal/daemon/acceptance_test.go index 7a76257d0..8cae37509 100644 --- a/internal/daemon/acceptance_test.go +++ b/internal/daemon/acceptance_test.go @@ -362,7 +362,8 @@ func TestRuntimeAcceptanceDaemonHelper(t *testing.T) { t.Fatal(err) } manager := rlm.NewManager(1) - value, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { kernel, kernelErr := rlm.NewKernel(rlm.KernelOptions{ Command: []string{executable, "-test.run=^TestRuntimeAcceptanceKernelWorker$", "--", "-acceptance-start", filepath.Join(home, "kernel-starts.log")}, Manager: manager, Host: acceptanceHost{corpus: string(corpus)}, diff --git a/internal/daemon/actor_control_test.go b/internal/daemon/actor_control_test.go index ce2cf1feb..fbcd51e10 100644 --- a/internal/daemon/actor_control_test.go +++ b/internal/daemon/actor_control_test.go @@ -37,7 +37,8 @@ func newIdleActorSession(t *testing.T, runner Runner) *Session { if err != nil { t.Fatal(err) } - root := newSession(store, meta, authority, Components{Runner: runner}) + processes := newTestProcesses(t) + root := newSession(store, processes, meta, authority, Components{Runner: runner}) t.Cleanup(root.supervisor.stop) return root } diff --git a/internal/daemon/agent_session.go b/internal/daemon/agent_session.go index a641b1fcd..d22b65492 100644 --- a/internal/daemon/agent_session.go +++ b/internal/daemon/agent_session.go @@ -629,7 +629,7 @@ func (session *AgentSession) bind(root *Session) error { if root.executors != nil { session.agent.Services.SetCustomTools(root.definition.ID, root.definitionRevision, customTools(root.definition), root.executors) } - if err := session.agent.Services.BindDispatcher(root.store, root.store.Workspaces(), root.store.Processes(), root.authority); err != nil { + if err := session.agent.Services.BindDispatcher(root.store, root.store.Workspaces(), root.processes, root.authority); err != nil { return err } session.agent.SetSessionID(root.id) diff --git a/internal/daemon/architecture_test.go b/internal/daemon/architecture_test.go index 79c71db2a..18a947f8a 100644 --- a/internal/daemon/architecture_test.go +++ b/internal/daemon/architecture_test.go @@ -1,6 +1,7 @@ package daemon import ( + "go/ast" "go/parser" "go/token" "io/fs" @@ -122,3 +123,21 @@ func TestArchitectureContainsNoClassicRuntimeSurface(t *testing.T) { } } } + +func TestArchitectureKeepsProcessConstructionOutOfStorage(t *testing.T) { + root := repositoryRoot(t) + for path, body := range productionGoFiles(t, filepath.Join(root, "internal", "session")) { + file, err := parser.ParseFile(token.NewFileSet(), path, body, 0) + if err != nil { + t.Fatal(err) + } + ast.Inspect(file, func(node ast.Node) bool { + if call, ok := node.(*ast.CallExpr); ok { + if constructor, ok := call.Fun.(*ast.SelectorExpr); ok && constructor.Sel.Name == "NewProcessManager" { + t.Errorf("storage constructs a live process manager: %s", path) + } + } + return true + }) + } +} diff --git a/internal/daemon/autostart_test.go b/internal/daemon/autostart_test.go index 25ef990da..0ea39dc8a 100644 --- a/internal/daemon/autostart_test.go +++ b/internal/daemon/autostart_test.go @@ -12,6 +12,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -190,10 +191,12 @@ func startTestServer(path string, paths RuntimePaths, buildID string, generation if err != nil { return runningServer{}, err } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := capability.NewProcessManager() + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { + _ = processes.Close() _ = store.Close() return runningServer{}, err } diff --git a/internal/daemon/browser_provider_test.go b/internal/daemon/browser_provider_test.go index 88a09a1c5..f31bb1f8f 100644 --- a/internal/daemon/browser_provider_test.go +++ b/internal/daemon/browser_provider_test.go @@ -93,7 +93,8 @@ func browserHarness(t *testing.T) (*Daemon, *Server, string) { t.Helper() store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) root := createRoot(t, store) - d, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + d, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -838,7 +839,8 @@ func TestBrowserToolHostScreenshotStoredWithOwnAuthority(t *testing.T) { } services := tools.NewServices() services.SetGate(func(context.Context, tools.GateRequest) (tools.GateDecision, string) { return tools.GateAllowOnce, "" }) - d, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + d, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: NewToolRunner(services)}, nil }) if err != nil { diff --git a/internal/daemon/budget_test.go b/internal/daemon/budget_test.go index bc004d7b7..87e9dc10a 100644 --- a/internal/daemon/budget_test.go +++ b/internal/daemon/budget_test.go @@ -18,7 +18,8 @@ import ( func TestBudgetCommandsRouteThroughRealSessionActor(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -61,7 +62,8 @@ func TestBudgetCommandsRouteThroughRealSessionActor(t *testing.T) { func TestModelCallBudgetAccountsPriceElapsedAndActiveOperation(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -112,7 +114,8 @@ func TestModelAccountingFailureRetriesSettlementWithoutProviderReplay(t *testing path := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, path) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -194,7 +197,8 @@ func TestModelAccountingFailureRetriesSettlementWithoutProviderReplay(t *testing func TestModelAccountingShutdownFlushesRetainedOutcome(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -225,7 +229,8 @@ func TestModelAccountingShutdownFlushesRetainedOutcome(t *testing.T) { func TestUnlimitedModelCallsShareAccountingWithoutDefaultDenial(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -299,7 +304,8 @@ func TestUnlimitedModelCallsShareAccountingWithoutDefaultDenial(t *testing.T) { func TestFiniteModelCapStopsRetryAfterUnknownUsage(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/cancel_command_test.go b/internal/daemon/cancel_command_test.go index 11b1b7fec..8518bd731 100644 --- a/internal/daemon/cancel_command_test.go +++ b/internal/daemon/cancel_command_test.go @@ -15,7 +15,8 @@ func TestExactCommandCancellationBeforeAndAfterTurnStart(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "runtime.db")) rootID := createRoot(t, store) started := make(chan struct{}, 3) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{turn: func(ctx context.Context, _ string, _ bool) (string, error) { started <- struct{}{} <-ctx.Done() diff --git a/internal/daemon/child_commit_test.go b/internal/daemon/child_commit_test.go index 231524593..c1c826ca7 100644 --- a/internal/daemon/child_commit_test.go +++ b/internal/daemon/child_commit_test.go @@ -156,7 +156,8 @@ func TestChildCommitFailureInterruptsRootWithoutFalseSuccess(t *testing.T) { t.Cleanup(func() { _ = store.Close() }) targetID, otherID := createRoot(t, store), createRoot(t, store) runtimes := map[string]*RecursiveRuntime{} - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD limits := rlm.DefaultLimits() diff --git a/internal/daemon/client_admission_test.go b/internal/daemon/client_admission_test.go index 78a04e55c..5dab73bc9 100644 --- a/internal/daemon/client_admission_test.go +++ b/internal/daemon/client_admission_test.go @@ -20,7 +20,8 @@ func TestClientAcceptancePrecedesProviderConstructionAndSurvivesDisconnect(t *te unblock := sync.OnceFunc(func() { close(release) }) defer unblock() var constructed atomic.Int32 - value, err := New(store, func(ctx context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(ctx context.Context, meta session.Meta, _ []llm.Message) (Components, error) { constructed.Add(1) if meta.Model == "replacement" { close(entered) @@ -101,7 +102,8 @@ func TestReplacementPreparationClosesPartialFactoryResult(t *testing.T) { func TestCommandAcceptanceRetriesDoNotRetainReceipts(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "runtime.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{turn: func(ctx context.Context, _ string, _ bool) (string, error) { <-ctx.Done(); return "", ctx.Err() }}}, nil }) if err != nil { diff --git a/internal/daemon/client_control_archive_test.go b/internal/daemon/client_control_archive_test.go index 03033fc08..79b93acde 100644 --- a/internal/daemon/client_control_archive_test.go +++ b/internal/daemon/client_control_archive_test.go @@ -27,7 +27,8 @@ func TestClientArchiveIsDurableIdempotentAndDoesNotStopWork(t *testing.T) { return "", ctx.Err() } }} - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -108,7 +109,8 @@ func TestControlSessionMetadataCommandWhenRootCannotOpen(t *testing.T) { if err := store.SetWorkingDirectory(rootID, missing); err != nil { t.Fatal(err) } - owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { // Production runner construction stats the workspace; mirror that here. if _, err := os.Stat(meta.CWD); err != nil { return Components{}, err diff --git a/internal/daemon/client_control_behavior_test.go b/internal/daemon/client_control_behavior_test.go index b3672bb0c..2dfdbff53 100644 --- a/internal/daemon/client_control_behavior_test.go +++ b/internal/daemon/client_control_behavior_test.go @@ -31,7 +31,8 @@ func TestClientCompactionRetryRestoresHistoryOnceAndKeepsEarlierSummary(t *testi } } runner := &compactingRunner{fakeRunner: &fakeRunner{}} - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -70,7 +71,8 @@ func TestClientModelDefaultPersistenceAndDeferredReload(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runtime := &reloadTestRuntime{} - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}, Runtime: runtime}, nil }) if err != nil { diff --git a/internal/daemon/client_control_boundaries_test.go b/internal/daemon/client_control_boundaries_test.go index 6e7e020ea..d1cb3a007 100644 --- a/internal/daemon/client_control_boundaries_test.go +++ b/internal/daemon/client_control_boundaries_test.go @@ -28,7 +28,8 @@ func TestClientValidationFailuresAreDurableAndLeaveSettingsUntouched(t *testing. store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}} - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -97,7 +98,8 @@ func TestClientModelReplacementPersistsDefaultWithoutForgettingExplicitOff(t *te if err := store.SetEffort(rootID, "off"); err != nil { t.Fatal(err) } - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/client_control_compaction_test.go b/internal/daemon/client_control_compaction_test.go index 2829ca2b3..447edc2d8 100644 --- a/internal/daemon/client_control_compaction_test.go +++ b/internal/daemon/client_control_compaction_test.go @@ -43,7 +43,8 @@ func TestClientCompactionConfigurationUsesProviderValidation(t *testing.T) { } store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }, providers) if err != nil { diff --git a/internal/daemon/client_control_test.go b/internal/daemon/client_control_test.go index 04349249e..77876c7a5 100644 --- a/internal/daemon/client_control_test.go +++ b/internal/daemon/client_control_test.go @@ -59,7 +59,8 @@ func TestToolHostRunsOnlyRestrictedToolCommands(t *testing.T) { t.Fatal(err) } var agentConstructions atomic.Int32 - owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { if meta.Kind != session.SessionKindToolHost { agentConstructions.Add(1) return Components{}, errors.New("unexpected model session") @@ -104,7 +105,8 @@ func TestToolHostRunsOnlyRestrictedToolCommands(t *testing.T) { func TestClientControlCommandsAreActorOwnedAndIdempotent(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -205,7 +207,8 @@ func TestClientCancelStopsOnlyCurrentTurn(t *testing.T) { <-ctx.Done() return "", ctx.Err() }} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -274,7 +277,8 @@ func TestShellCommandLeavesActorResponsiveAndQueuesTurns(t *testing.T) { runner := &blockingShellRunner{ fakeRunner: &fakeRunner{}, started: make(chan struct{}), release: make(chan struct{}), } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -393,7 +397,8 @@ func TestExplicitCompactionRunsOffActorAndRecordsDurableSummary(t *testing.T) { t.Fatal(err) } runner := &compactingRunner{fakeRunner: &fakeRunner{}} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -461,7 +466,8 @@ func TestClearHistoryAtomicallyDropsDerivedStateAndReleasesSnapshots(t *testing. t.Fatal(err) } runner := &snapshottingHistoryRunner{fakeRunner: &fakeRunner{}} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -529,7 +535,8 @@ func TestGoalFromContextRunsOnceOffActorAndStartsGoal(t *testing.T) { runner := &goalFormingRunner{fakeRunner: &fakeRunner{ turn: func(context.Context, string, bool) (string, error) { return "GOAL_MET — verified", nil }, }} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -567,7 +574,8 @@ func TestTurnSnapshotAndRewindAreDaemonOwnedAndIdempotent(t *testing.T) { runner := &snapshottingHistoryRunner{fakeRunner: &fakeRunner{ history: []llm.Message{{Role: "system", Content: "system"}}, }} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -652,7 +660,8 @@ func TestResponseEndpointForkAndRewindKeepTrailingTools(t *testing.T) { } store = openStore(t, path) runner := &compactingRunner{fakeRunner: &fakeRunner{}} - owner, err := New(store, func(_ context.Context, _ session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, _ session.Meta, history []llm.Message) (Components, error) { if len(history) != 9 || history[0].Role != "system" || history[0].RawSequence != 2*step { t.Fatalf("fixture did not restore compacted raw view: %+v", history) } @@ -738,7 +747,8 @@ func TestGoalRunUsesOneControlCommandAndStartsTheGoalTurn(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{turn: func(context.Context, string, bool) (string, error) { return "GOAL_MET — done", nil }} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -840,7 +850,8 @@ func TestClientControlSurfaceDelegatesEveryAuthorityToDaemon(t *testing.T) { rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}, workingDirectory: t.TempDir()} mcpManager := &controlSurfaceMCP{} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner, MCP: mcpManager}, nil }) if err != nil { @@ -906,7 +917,8 @@ func TestClientControlRejectsRootRuntimeMutationDuringTurn(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}, workingDirectory: t.TempDir()} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -953,7 +965,8 @@ func TestClientControlRejectsInvalidActionsDurably(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}, workingDirectory: t.TempDir()} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner, MCP: &controlSurfaceMCP{}}, nil }) if err != nil { @@ -1018,7 +1031,8 @@ func TestClientControlRejectsInvalidActionsDurably(t *testing.T) { func TestProtocolClientCommandsFailClosedWithoutOptionalRunnerCapabilities(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -1060,7 +1074,8 @@ func TestProtocolClientCommandsFailClosedWithoutOptionalRunnerCapabilities(t *te func TestClientControlReportsUnsupportedRunnerCapabilities(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -1131,7 +1146,8 @@ func TestAsyncClientControlFailuresSettleDurably(t *testing.T) { if err := store.SetSnapshot(rootID, 1, "snapshot-ref"); err != nil { t.Fatal(err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &failingAsyncRunner{fakeRunner: &fakeRunner{}}}, nil }) if err != nil { @@ -1180,7 +1196,8 @@ func TestMCPImportDefersRuntimeReloadUntilChildrenAreIdle(t *testing.T) { runtime := &reloadTestRuntime{} runtime.running.Store(true) var constructions atomic.Int32 - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { constructions.Add(1) return Components{Runner: &fakeRunner{}, Runtime: runtime}, nil }) @@ -1224,7 +1241,8 @@ func TestEffortControlPreservesExplicitOffAndGlobalDefaultOnCompatibilityChange( store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -1262,7 +1280,8 @@ func TestEffortControlPreservesExplicitOffAndGlobalDefaultOnCompatibilityChange( if err := store.SetEffort(rootID, "high"); err != nil { t.Fatal(err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -1310,7 +1329,8 @@ func TestModelReplacementRejectsUnsafeFactories(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) calls := 0 - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { calls++ if calls == 1 || test.replacement == nil { return Components{Runner: test.initial}, nil @@ -1354,7 +1374,9 @@ func TestProductionAgentRunnerControlAdapters(t *testing.T) { services.SetBrowser(browser.NewManager(browser.ModeLive), false) services.SetComputerPolicy(computer.NewPolicy(nil, nil, false)) services.SetDiagnostics(lsp.NewManager(nil)) - if err := services.BindDispatcher(store, store.Workspaces(), store.Processes(), authority); err != nil { + processes := newTestProcesses(t) + t.Cleanup(services.Close) + if err := services.BindDispatcher(store, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } meta, _, err := store.Load(rootID) @@ -1480,7 +1502,11 @@ func TestClientControlStoreFailuresAndAsyncRecovery(t *testing.T) { t.Fatal(err) } runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}, workingDirectory: t.TempDir()} - root := newSession(store, meta, authority, Components{Runner: runner}) + processes := newTestProcesses(t) + root := newSession(store, processes, meta, authority, Components{Runner: runner}) + if err := processes.Close(); err != nil { + t.Fatal(err) + } if err := store.Close(); err != nil { t.Fatal(err) } diff --git a/internal/daemon/command_test.go b/internal/daemon/command_test.go index 56e104ec5..73ae9d6fa 100644 --- a/internal/daemon/command_test.go +++ b/internal/daemon/command_test.go @@ -14,7 +14,8 @@ func TestProtocolCommandRetryAttachesToOneRootExecution(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/control_test.go b/internal/daemon/control_test.go index 3a52c4878..e2daff390 100644 --- a/internal/daemon/control_test.go +++ b/internal/daemon/control_test.go @@ -20,7 +20,8 @@ import ( func TestControlSessionCreationIsIdempotent(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -138,7 +139,8 @@ func TestControlRouteWaitsForAcceptedWorkAfterCancellation(t *testing.T) { func TestControlListsDeletesAndCheckpointsWithDurableOutcomes(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index fa0f4369a..227ca67e2 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -24,10 +24,11 @@ type rootEntry struct { err error } -// Daemon owns the durable store and exactly one live actor per opened root. +// Daemon owns the durable store, shared processes, and one live actor per opened root. type Daemon struct { providers *providersvc.ProviderService store *session.Store + processes *capability.ProcessManager factory Factory control *Control executors *executorRegistry @@ -48,10 +49,14 @@ type Daemon struct { } // New applies daemon-startup recovery before any root can be opened. -func New(store *session.Store, factory Factory, providers ...*providersvc.ProviderService) (*Daemon, error) { +// On success it takes ownership of store and processes; failures leave both caller-owned. +func New(store *session.Store, processes *capability.ProcessManager, factory Factory, providers ...*providersvc.ProviderService) (*Daemon, error) { if store == nil || factory == nil { return nil, errors.New("daemon requires a store and root factory") } + if processes == nil { + return nil, errors.New("daemon requires a process manager") + } if !store.AcquireDaemon() { return nil, errors.New("store already has a daemon owner") } @@ -60,7 +65,7 @@ func New(store *session.Store, factory Factory, providers ...*providersvc.Provid return nil, err } ctx, cancel := context.WithCancel(context.Background()) - daemon := &Daemon{store: store, factory: factory, executors: newExecutorRegistry(), browserProviders: newBrowserProviders(store), terminals: terminal.NewManager(ctx), ctx: ctx, cancel: cancel, roots: make(map[string]*rootEntry)} + daemon := &Daemon{store: store, processes: processes, factory: factory, executors: newExecutorRegistry(), browserProviders: newBrowserProviders(store), terminals: terminal.NewManager(ctx), ctx: ctx, cancel: cancel, roots: make(map[string]*rootEntry)} if len(providers) > 0 { daemon.providers = providers[0] } @@ -304,7 +309,7 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err if components.Runtime != nil { err = errors.Join(err, safeClose("runtime", components.Runtime.Close)) } - err = errors.Join(err, d.store.Processes().StopRoot(meta.ID)) + err = errors.Join(err, d.processes.StopRoot(meta.ID)) if root != nil { root.supervisor.stop() root.supervisor.wait() @@ -321,7 +326,7 @@ func (d *Daemon) open(meta session.Meta, history []llm.Message) (_ *Session, err // Bind can restore and wake children, so restore their inherited policy first. runner.SetExternalPermissions(mode == session.PermissionModePrompt) } - root = newSession(d.store, meta, authority, components, d.factory) + root = newSession(d.store, d.processes, meta, authority, components, d.factory) root.providers = d.providers root.titleChanged = d.notifyTitleChanged root.executors = d.executors @@ -350,7 +355,7 @@ func configureMCP(root *Session, components Components) { if manager, ok := components.MCP.(interface { SetProcessOptions(*capability.ProcessManager, string, string, map[string]string) }); ok { - manager.SetProcessOptions(root.store.Processes(), root.id, root.WorkingDirectory(), nil) + manager.SetProcessOptions(root.processes, root.id, root.WorkingDirectory(), nil) } if supervised, ok := components.MCP.(interface { SetLauncher(func(string, func()) bool) @@ -362,7 +367,7 @@ func configureMCP(root *Session, components Components) { } } -// Close stops roots outside the registry lock, then closes the shared store. +// Close stops roots outside the registry lock, then closes shared processes and the store. func (d *Daemon) Close() error { d.once.Do(func() { defer d.store.ReleaseDaemon() @@ -400,7 +405,7 @@ func (d *Daemon) Close() error { } d.wg.Wait() <-d.control.done - d.err = d.store.Close() + d.err = errors.Join(d.processes.Close(), d.store.Close()) }) return d.err } diff --git a/internal/daemon/daemon_process_ownership_test.go b/internal/daemon/daemon_process_ownership_test.go index 7a940fa74..1d20c3dd0 100644 --- a/internal/daemon/daemon_process_ownership_test.go +++ b/internal/daemon/daemon_process_ownership_test.go @@ -21,12 +21,13 @@ func TestDaemonProcessEnvironmentSnapshotsBeforeConstruction(t *testing.T) { const variable = "LC_WHIP_PROCESS_OWNERSHIP" t.Setenv(variable, "at-store-open") store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - processes := store.Processes() + processes := capability.NewProcessManager() defer store.Close() + defer processes.Close() rootID := createRoot(t, store) t.Setenv(variable, "before-daemon-new") services := tools.NewServices() - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: NewToolRunner(services)}, nil }) if err != nil { @@ -57,7 +58,8 @@ func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, path) defer store.Close() - processes := store.Processes() + processes := capability.NewProcessManager() + defer processes.Close() rootID := createRoot(t, store) if err := store.SetBudgetLimit(t.Context(), rootID, "", session.BudgetTokens, 100); err != nil { t.Fatal(err) @@ -68,10 +70,10 @@ func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { } defer fixtureDB.Close() const marker = "fixture process recovery failure" - if _, err := fixtureDB.Exec(`CREATE TRIGGER reject_process_ownership_recovery BEFORE UPDATE ON budgets BEGIN SELECT RAISE(ABORT,'fixture process recovery failure'); END`); err != nil { + if _, err := fixtureDB.ExecContext(t.Context(), `CREATE TRIGGER reject_process_ownership_recovery BEFORE UPDATE ON budgets BEGIN SELECT RAISE(ABORT,'fixture process recovery failure'); END`); err != nil { t.Fatal(err) } - defer fixtureDB.Exec(`DROP TRIGGER IF EXISTS reject_process_ownership_recovery`) + defer fixtureDB.ExecContext(t.Context(), `DROP TRIGGER IF EXISTS reject_process_ownership_recovery`) var stopped atomic.Int32 if _, err := processes.RegisterStop(rootID, func() error { stopped.Add(1); return nil }); err != nil { t.Fatal(err) @@ -79,7 +81,7 @@ func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil } - owner, err := New(store, factory) + owner, err := New(store, processes, factory) if owner != nil || err == nil || !strings.Contains(err.Error(), marker) { t.Fatalf("recovery result = %v, %v", owner, err) } @@ -98,10 +100,10 @@ func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { t.Fatal("failed recovery retained the daemon ownership guard") } store.ReleaseDaemon() - if _, err := fixtureDB.Exec(`DROP TRIGGER reject_process_ownership_recovery`); err != nil { + if _, err := fixtureDB.ExecContext(t.Context(), `DROP TRIGGER reject_process_ownership_recovery`); err != nil { t.Fatal(err) } - owner, err = New(store, factory) + owner, err = New(store, processes, factory) if err != nil { t.Fatalf("retry with the same resources: %v", err) } @@ -117,9 +119,10 @@ func TestNewRecoveryFailureLeavesResourcesCallerOwned(t *testing.T) { func TestDaemonCloseStopsProcessesBeforeStoreAndCachesErrors(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) defer store.Close() - processes := store.Processes() + processes := capability.NewProcessManager() + defer processes.Close() rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -152,7 +155,7 @@ func TestDaemonCloseStopsProcessesBeforeStoreAndCachesErrors(t *testing.T) { if _, err := store.LoadMeta(rootID); err == nil { t.Fatal("database remained open after daemon shutdown") } - if repeated := owner.Close(); repeated != first { + if repeated := owner.Close(); repeated != first { //nolint:errorlint // Close must return the identical cached error, not only matching wrapped errors. t.Fatalf("Close did not return the cached error: first=%v repeated=%v", first, repeated) } for i, count := range counts { @@ -169,11 +172,12 @@ func TestDaemonCloseStopsProcessesBeforeStoreAndCachesErrors(t *testing.T) { func TestFailedRootBindStopsOnlyItsProcessScope(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) defer store.Close() - processes := store.Processes() + processes := capability.NewProcessManager() + defer processes.Close() healthyID, failingID := createRoot(t, store), createRoot(t, store) bindErr := errors.New("fixture root bind failure") var healthyStops, failingStops atomic.Int32 - owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { services := tools.NewServices() return Components{Runner: NewToolRunner(services), Bind: func(context.Context, *Session) error { options := services.ProcessOptions() @@ -234,3 +238,43 @@ func TestFailedRootBindStopsOnlyItsProcessScope(t *testing.T) { t.Fatalf("owner shutdown did not close manager: %v", err) } } + +func TestNewRequiresExplicitProcessOwnerAfterExistingInputChecks(t *testing.T) { + store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) + defer store.Close() + processes := capability.NewProcessManager() + defer processes.Close() + factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { + return Components{Runner: &fakeRunner{}}, nil + } + for _, test := range []struct { + name string + store *session.Store + processes *capability.ProcessManager + factory Factory + want string + }{ + {name: "nil store", factory: factory, want: "daemon requires a store and root factory"}, + {name: "nil factory", store: store, want: "daemon requires a store and root factory"}, + {name: "nil processes", store: store, factory: factory, want: "daemon requires a process manager"}, + {name: "nil factory with processes", store: store, processes: processes, want: "daemon requires a store and root factory"}, + } { + t.Run(test.name, func(t *testing.T) { + if owner, err := New(test.store, test.processes, test.factory); owner != nil || err == nil || err.Error() != test.want { + t.Fatalf("New = %v, %v; want %q", owner, err, test.want) + } + }) + } + if !store.AcquireDaemon() { + t.Fatal("invalid constructor arguments acquired the daemon guard") + } + store.ReleaseDaemon() + if _, err := store.LoadMeta(createRoot(t, store)); err != nil { + t.Fatal(err) + } + unregister, err := processes.RegisterStop("after-invalid-new", func() error { return nil }) + if err != nil { + t.Fatal(err) + } + unregister() +} diff --git a/internal/daemon/daemon_test.go b/internal/daemon/daemon_test.go index 4566fb69e..0f8b4d91f 100644 --- a/internal/daemon/daemon_test.go +++ b/internal/daemon/daemon_test.go @@ -35,7 +35,8 @@ func TestResumeActiveIsolatesFailuresAndAllowsRetry(t *testing.T) { failure := &config.UnknownModelError{Model: "model"} repaired := false var attempts []string - value, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { attempts = append(attempts, meta.ID) if meta.ID == ids[1] && !repaired { return Components{}, failure @@ -86,7 +87,8 @@ func TestResumeActiveCancellation(t *testing.T) { ctx, cancel := context.WithCancel(t.Context()) defer cancel() attempts := 0 - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { attempts++ cancel() return Components{}, errors.New("session initialization failed") diff --git a/internal/daemon/definition_test.go b/internal/daemon/definition_test.go index 463ab14d8..2cfcc6415 100644 --- a/internal/daemon/definition_test.go +++ b/internal/daemon/definition_test.go @@ -90,7 +90,8 @@ func TestDefinitionSurfaceDisablesAutomaticTitle(t *testing.T) { runner := &titleRunner{fakeRunner: &fakeRunner{}, title: "Never Applied", finished: make(chan struct{})} definition := agentdef.Coding() definition.Surface.AutoTitle = false - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner, Definition: definition}, nil }) if err != nil { diff --git a/internal/daemon/effort_vocabulary_test.go b/internal/daemon/effort_vocabulary_test.go index 2e1da9a93..2cd3978d8 100644 --- a/internal/daemon/effort_vocabulary_test.go +++ b/internal/daemon/effort_vocabulary_test.go @@ -18,7 +18,8 @@ import ( func TestSessionCreationStoresConcreteEffort(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -78,7 +79,8 @@ func TestOpenResolvesLegacyBlankEffort(t *testing.T) { t.Fatalf("fixture effort = %q %v", meta.Effort, err) } constructed := "" - value, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { constructed = meta.Effort return Components{Runner: &fakeRunner{}}, nil }) diff --git a/internal/daemon/execution_engine_test.go b/internal/daemon/execution_engine_test.go index c7d483771..d729ccd3c 100644 --- a/internal/daemon/execution_engine_test.go +++ b/internal/daemon/execution_engine_test.go @@ -23,7 +23,8 @@ func TestSessionCreateFreezesEngineBeforeDefaultsChange(t *testing.T) { t.Fatal(err) } store := openStore(t, filepath.Join(t.TempDir(), "engine.db")) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/host_test.go b/internal/daemon/host_test.go index 0299f0a73..38d7ee6f7 100644 --- a/internal/daemon/host_test.go +++ b/internal/daemon/host_test.go @@ -240,7 +240,8 @@ func TestHostReadsDoNotOpenRootsAndQuestionsDisappear(t *testing.T) { t.Setenv("INFERENCE_API_KEY", "") store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) opens := 0 - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { opens++ return Components{Runner: &fakeRunner{}}, nil }) diff --git a/internal/daemon/identity_test.go b/internal/daemon/identity_test.go index 3c8b24676..3f9fe7543 100644 --- a/internal/daemon/identity_test.go +++ b/internal/daemon/identity_test.go @@ -42,7 +42,8 @@ func (r *permissionModeRunner) ResolvePermission(permissionID string, decision c func TestTrustedClientPermissionIdentityMethodsAreRemoved(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -75,7 +76,8 @@ func TestTrustedClientPermissionDecisionsAreScopedAndIdempotent(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) otherRootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -161,7 +163,8 @@ func TestTrustedClientPermissionModesUseOrdinaryCommands(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &permissionModeRunner{fakeRunner: &fakeRunner{}} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -205,7 +208,8 @@ func TestTrustedClientPermissionModesUseOrdinaryCommands(t *testing.T) { func TestRootSnapshotIsACompleteAuthoritativeClientView(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/inbox_queue_test.go b/internal/daemon/inbox_queue_test.go index 2da17af52..2b14083d4 100644 --- a/internal/daemon/inbox_queue_test.go +++ b/internal/daemon/inbox_queue_test.go @@ -88,7 +88,8 @@ func TestQueueControlsThroughRuntimeCommand(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "runtime.db")) rootID := createRoot(t, store) started := make(chan struct{}, 1) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{turn: func(ctx context.Context, _ string, _ bool) (string, error) { started <- struct{}{} <-ctx.Done() diff --git a/internal/daemon/input_lifecycle_test.go b/internal/daemon/input_lifecycle_test.go index 11d972f0d..194d48caf 100644 --- a/internal/daemon/input_lifecycle_test.go +++ b/internal/daemon/input_lifecycle_test.go @@ -23,7 +23,8 @@ func TestLifecycleBoundaryReadFailurePreservesClaimForRetry(t *testing.T) { dir := t.TempDir() store := openStore(t, filepath.Join(dir, "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -120,7 +121,8 @@ func TestLifecycleRootPreservesLargeInput(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{} - owner, err := New(store, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -201,7 +203,8 @@ func TestLifecycleMultipartAndMalformedInput(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &lifecyclePartsRunner{} - owner, err := New(store, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -443,7 +446,8 @@ func TestLifecycleUnsupportedPartsNeverReuseRunnerJournal(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) id := createRoot(t, store) runner := &lifecycleJournalRunner{} - owner, err := New(store, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, sessionstore.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/interactive_test.go b/internal/daemon/interactive_test.go index 38836d27c..5f4b7e818 100644 --- a/internal/daemon/interactive_test.go +++ b/internal/daemon/interactive_test.go @@ -101,7 +101,8 @@ func TestProtocolRedactsTerminalInputFromDurableState(t *testing.T) { store := openStore(t, path) rootID := createRoot(t, store) runner := &terminalFakeRunner{inputs: make(chan terminalInput, 1)} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/mailbox_delivery_test.go b/internal/daemon/mailbox_delivery_test.go index cdccfae81..74016c94f 100644 --- a/internal/daemon/mailbox_delivery_test.go +++ b/internal/daemon/mailbox_delivery_test.go @@ -24,6 +24,7 @@ func TestRootMailboxFailureRequiresExplicitInputAcrossRestart(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, dbPath) rootID := createRoot(t, store) + processes := newTestProcesses(t) open := func() (*Daemon, *Session, *fakeRunner) { runner := &fakeRunner{turn: func(_ context.Context, input string, _ bool) (string, error) { if input == "resume successfully" { @@ -31,7 +32,7 @@ func TestRootMailboxFailureRequiresExplicitInputAcrossRestart(t *testing.T) { } return "", failure }} - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -86,6 +87,7 @@ func TestRootMailboxFailureRequiresExplicitInputAcrossRestart(t *testing.T) { t.Fatal(err) } store = openStore(t, dbPath) + processes = newTestProcesses(t) _, root, runner = open() for range 10 { root.notify() @@ -142,7 +144,8 @@ func mailboxDeliveryFixture(t *testing.T) (*session.Store, *Session, *AgentSessi t.Helper() store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/manual_compaction_test.go b/internal/daemon/manual_compaction_test.go index 2e2584db0..16fad5ab0 100644 --- a/internal/daemon/manual_compaction_test.go +++ b/internal/daemon/manual_compaction_test.go @@ -39,10 +39,11 @@ func TestManualCompactionUsesRawSequencesAfterFocusAndRestart(t *testing.T) { if err := store.Save(rootID, 1, raw[:29], "model", "provider"); err != nil { t.Fatal(err) } + processes := newTestProcesses(t) openOwner := func() (*Daemon, *Session, *AgentSession) { t.Helper() var runner *AgentSession - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "system", tools.NewServices()) value.ContextLimit = 4000 value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD @@ -84,6 +85,7 @@ func TestManualCompactionUsesRawSequencesAfterFocusAndRestart(t *testing.T) { t.Fatal(err) } store = openStore(t, path) + processes = newTestProcesses(t) _, restored, err := store.Load(rootID) if err != nil || len(restored) != 5 || restored[0].RawSequence != expectedCutoff || restored[1].Role != "user" || restored[1].RawSequence != expectedCutoff || restored[2].RawSequence != expectedCutoff+1 || restored[3].Role != "tool" || restored[3].ToolCallID != restored[2].ToolCalls[0].ID { @@ -119,7 +121,8 @@ func TestHistoryReplacementDoesNotResurrectCommittedJournalAsProvisional(t *test t.Fatal(err) } runner := &AgentSession{id: rootID, agent: agent.NewRuntime(nil, "model", 1024, "system", tools.NewServices()), turn: turnJournal{TurnID: "completed-turn", Messages: history}} - runner.root = newSession(store, meta, authority, Components{Runner: runner}) + processes := newTestProcesses(t) + runner.root = newSession(store, processes, meta, authority, Components{Runner: runner}) host := &recursiveHost{session: runner} replacement, err := store.RewindHistory(t.Context(), rootID, from) if err != nil { diff --git a/internal/daemon/mcp_import_service_test.go b/internal/daemon/mcp_import_service_test.go index 2f264b84a..3fe612b14 100644 --- a/internal/daemon/mcp_import_service_test.go +++ b/internal/daemon/mcp_import_service_test.go @@ -210,7 +210,8 @@ func TestMCPImportApplyValidatesBeforeWritingAndSkipsQuietly(t *testing.T) { func TestMCPBrandIconsFollowSuppliedProviderLifetime(t *testing.T) { _, providers, _ := mcpImportFixture(t) store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }, providers) if err != nil { diff --git a/internal/daemon/metadata_routing_test.go b/internal/daemon/metadata_routing_test.go index 01c1d195e..7a029b500 100644 --- a/internal/daemon/metadata_routing_test.go +++ b/internal/daemon/metadata_routing_test.go @@ -20,7 +20,8 @@ func TestColdMetadataReroutesAfterRootOpens(t *testing.T) { fakeRunner: &fakeRunner{}, title: "Generated title", started: make(chan struct{}), release: make(chan struct{}), finished: make(chan struct{}), } - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -130,7 +131,8 @@ func TestOpenReloadsMetadataAfterRegistryPublication(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) constructed := make(chan session.Meta, 1) - owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { constructed <- meta return Components{Runner: &fakeRunner{}}, nil }) diff --git a/internal/daemon/model_accounting_acceptance_test.go b/internal/daemon/model_accounting_acceptance_test.go index f98b6c95c..305708f12 100644 --- a/internal/daemon/model_accounting_acceptance_test.go +++ b/internal/daemon/model_accounting_acceptance_test.go @@ -61,7 +61,8 @@ func modelAccountingRuntimeAt(t *testing.T, path string, handler http.HandlerFun } } var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { client := llm.New(provider.URL, "local-test-key") client.MaxRetries = 1 value := agent.NewRuntime(client, "root-model", 128, "", tools.NewServices()) diff --git a/internal/daemon/model_admission_lock_test.go b/internal/daemon/model_admission_lock_test.go index 3ac4e0063..64bfaef57 100644 --- a/internal/daemon/model_admission_lock_test.go +++ b/internal/daemon/model_admission_lock_test.go @@ -14,7 +14,8 @@ import ( func TestModelAdmissionWaitingForActorDoesNotHoldAccountingLock(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/permission_mode_test.go b/internal/daemon/permission_mode_test.go index b657b6ff0..f58cd25e7 100644 --- a/internal/daemon/permission_mode_test.go +++ b/internal/daemon/permission_mode_test.go @@ -27,7 +27,8 @@ import ( func TestPermissionModeSnapshotAndUpdateEvent(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: NewToolRunner(tools.NewServices())}, nil }) if err != nil { @@ -82,7 +83,8 @@ func TestPermissionModeSnapshotAndUpdateEvent(t *testing.T) { func permissionModeOwner(t *testing.T, store *session.Store, factoryMode bool) *Daemon { t.Helper() - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { runner := NewToolRunner(tools.NewServices()).(*toolRunner) runner.SetExternalPermissions(factoryMode) return Components{Runner: runner}, nil @@ -266,10 +268,11 @@ func TestPermissionModeRestoresChildrenBeforeResumedWork(t *testing.T) { external := mode == session.PermissionModePrompt var runtime *RecursiveRuntime var runs, firstModes *sync.Map + processes := newTestProcesses(t) open := func() (*Daemon, *Session) { t.Helper() runs, firstModes = &sync.Map{}, &sync.Map{} - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD value.Services.SetExternalPermissions(!external) @@ -328,6 +331,7 @@ func TestPermissionModeRestoresChildrenBeforeResumedWork(t *testing.T) { t.Fatal(err) } store = openStore(t, path) + processes = newTestProcesses(t) // Queued durable input causes the retained child to wake inside Bind. if _, err := store.SendMailboxMessage(t.Context(), rootID, rootID, childID, session.MailboxSend{Subject: "resume", Body: "work again"}); err != nil { t.Fatal(err) diff --git a/internal/daemon/permission_test.go b/internal/daemon/permission_test.go index ba4376275..a5dca4e95 100644 --- a/internal/daemon/permission_test.go +++ b/internal/daemon/permission_test.go @@ -18,7 +18,8 @@ import ( func TestCapabilityAuthorityRoutesThroughRootActor(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -65,7 +66,8 @@ func TestDirectPermissionControlsStayRootScoped(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) otherRootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -118,7 +120,8 @@ func TestPermissionRuleResolvesCoveredPromptsAndSkipsFutureOnes(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -231,7 +234,8 @@ func TestPermissionRuleInExternalModeSkipsThePrimaryPrompt(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &permissionModeRunner{fakeRunner: &fakeRunner{}, external: true} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/prompt_test.go b/internal/daemon/prompt_test.go index a48ef823b..91f5f3791 100644 --- a/internal/daemon/prompt_test.go +++ b/internal/daemon/prompt_test.go @@ -390,7 +390,8 @@ func promptRuntimeProvider(t *testing.T) (<-chan llm.Request, *llm.Client) { func openPromptRuntime(t *testing.T, store *session.Store, rootID string, client *llm.Client) (*Daemon, *Session, *RecursiveRuntime) { t.Helper() var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(client, meta.Model, 128, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD value.ContextLimit = 65536 diff --git a/internal/daemon/provider_client_behavior_test.go b/internal/daemon/provider_client_behavior_test.go index a12cdfd53..a1a45cd75 100644 --- a/internal/daemon/provider_client_behavior_test.go +++ b/internal/daemon/provider_client_behavior_test.go @@ -39,7 +39,8 @@ func providerBehaviorFixture(t *testing.T) (*Server, *Client, *RootClient, strin t.Setenv("WHIPCODE_HOME", t.TempDir()) store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/provider_default_test.go b/internal/daemon/provider_default_test.go index 39d68837f..49eb6f993 100644 --- a/internal/daemon/provider_default_test.go +++ b/internal/daemon/provider_default_test.go @@ -23,7 +23,8 @@ func TestModelSelectionAppliesAndPersistsEffortTogether(t *testing.T) { rootID := createRoot(t, store) var mu sync.Mutex var built []session.Meta - owner, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { mu.Lock() built = append(built, meta) mu.Unlock() @@ -68,7 +69,8 @@ func TestModelSelectionAppliesAndPersistsEffortTogether(t *testing.T) { } closed = true store = openStore(t, path) - resumed, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes = newTestProcesses(t) + resumed, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { if meta.Model != "gpt-6-astra" || meta.Provider != "openai" || meta.Effort != "high" { t.Errorf("resume lost selection: %+v", meta) } diff --git a/internal/daemon/question_snapshot_test.go b/internal/daemon/question_snapshot_test.go index 288f3163a..e8e38d3b8 100644 --- a/internal/daemon/question_snapshot_test.go +++ b/internal/daemon/question_snapshot_test.go @@ -15,7 +15,8 @@ import ( func TestQuestionSnapshotCursorMatchesPendingState(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "runtime.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/recursive_runtime.go b/internal/daemon/recursive_runtime.go index e8a28ced4..bc34edd9f 100644 --- a/internal/daemon/recursive_runtime.go +++ b/internal/daemon/recursive_runtime.go @@ -438,7 +438,7 @@ func (runtime *RecursiveRuntime) restoreChildren(ctx context.Context) error { if err != nil { return err } - services, err := parent.agent.Services.CloneForAuthority(runtime.root.store, runtime.root.store.Workspaces(), runtime.root.store.Processes(), authority) + services, err := parent.agent.Services.CloneForAuthority(runtime.root.store, runtime.root.store.Workspaces(), runtime.root.processes, authority) if err != nil { return err } @@ -1249,7 +1249,7 @@ func (runtime *RecursiveRuntime) spawnAttempt(ctx context.Context, parent *Agent Operations: []string{"mcp.call"}, MCP: mcpTools, }) } - services, err := parent.agent.Services.CloneForAuthority(parent.root.store, parent.root.store.Workspaces(), parent.root.store.Processes(), authority) + services, err := parent.agent.Services.CloneForAuthority(parent.root.store, parent.root.store.Workspaces(), parent.root.processes, authority) if err != nil { return nil, err } diff --git a/internal/daemon/recursive_runtime_test.go b/internal/daemon/recursive_runtime_test.go index 35cd02a19..f2314c44a 100644 --- a/internal/daemon/recursive_runtime_test.go +++ b/internal/daemon/recursive_runtime_test.go @@ -64,7 +64,8 @@ func openRecursiveRuntime(t *testing.T, client *llm.Client, maxWorkers int, engi t.Fatal(err) } var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(client, "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD limits := rlm.DefaultLimits() @@ -94,7 +95,7 @@ func TestRecursiveRuntimeUsesOneInterfaceAtEveryDepth(t *testing.T) { streamText(w, "done") })) defer server.Close() - store, root, runtime := openRecursiveRuntime(t, llm.New(server.URL, "key"), 4) + _, root, runtime := openRecursiveRuntime(t, llm.New(server.URL, "key"), 4) runs := &sync.Map{} runtime.setRunTurnHook(observeRunTurn(runs)) receipt, err := root.Submit(t.Context(), "root work") @@ -124,7 +125,7 @@ func TestRecursiveRuntimeUsesOneInterfaceAtEveryDepth(t *testing.T) { waitAgentIdle(t, child) for _, node := range []*AgentSession{runtime.rootNode, child, grandchild} { - if options := node.agent.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != root.ID() { + if options := node.agent.Services.ProcessOptions(); options.Processes != root.processes || options.RootID != root.ID() { t.Fatalf("agent %q process scope = %p %q", node.name, options.Processes, options.RootID) } all := node.agent.AllTools() @@ -463,7 +464,8 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { rootID := createRoot(t, store) makeOwner := func(store *session.Store) (*Daemon, **RecursiveRuntime) { var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD limits := rlm.DefaultLimits() @@ -527,7 +529,7 @@ func TestRecursiveRuntimeRestoresRetainedAgentAndTranscript(t *testing.T) { t.Fatalf("retained child %q was not restored", childID) } for _, node := range []*AgentSession{second.rootNode, restored} { - if options := node.agent.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != secondRoot.ID() { + if options := node.agent.Services.ProcessOptions(); options.Processes != secondOwner.processes || options.RootID != secondRoot.ID() { t.Fatalf("restored agent %q process scope = %p %q", node.name, options.Processes, options.RootID) } } @@ -574,7 +576,8 @@ func TestQueuedInitialAgentPromptSurvivesRestartExactlyOnce(t *testing.T) { } makeOwner := func(store *session.Store) (*Daemon, **RecursiveRuntime) { var runtime *RecursiveRuntime - owner, ownerErr := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, ownerErr := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD limits := rlm.DefaultLimits() @@ -911,7 +914,8 @@ func TestChildScratchSurvivesDaemonRestart(t *testing.T) { } makeOwner := func(store *session.Store) (*Daemon, **RecursiveRuntime) { var runtime *RecursiveRuntime - owner, ownerErr := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, ownerErr := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD var runtimeErr error diff --git a/internal/daemon/report_restore_test.go b/internal/daemon/report_restore_test.go index e122821d1..82746cf5b 100644 --- a/internal/daemon/report_restore_test.go +++ b/internal/daemon/report_restore_test.go @@ -36,7 +36,8 @@ func TestReportModeRestoresIdentityAndCompletionBehavior(t *testing.T) { rootID := createRoot(t, store) makeOwner := func(store *session.Store) (*Daemon, *Session, *RecursiveRuntime) { var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(llm.New(server.URL, "key"), "model", 1024, "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD limits := rlm.DefaultLimits() diff --git a/internal/daemon/restart_test.go b/internal/daemon/restart_test.go index 17b48ddaa..f18b50bab 100644 --- a/internal/daemon/restart_test.go +++ b/internal/daemon/restart_test.go @@ -22,7 +22,8 @@ func TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution(t *test <-ctx.Done() return "", ctx.Err() }} - oldDaemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + oldDaemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: oldRunner}, nil }) if err != nil { @@ -55,8 +56,14 @@ func TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution(t *test if err != nil { t.Fatal(err) } + processes = newTestProcesses(t) + unregister, err := processes.RegisterStop("reopened-owner", func() error { return nil }) + if err != nil { + t.Fatalf("reopened owner has no live process manager: %v", err) + } + unregister() newRunner := &fakeRunner{} - newDaemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + newDaemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: newRunner}, nil }) if err != nil { diff --git a/internal/daemon/root_client_test.go b/internal/daemon/root_client_test.go index 061992434..1786e7f4c 100644 --- a/internal/daemon/root_client_test.go +++ b/internal/daemon/root_client_test.go @@ -492,7 +492,8 @@ func TestRootClientReceivesEventsAfterExpiredCursorSnapshot(t *testing.T) { t.Fatal(err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/runtime_parity_test.go b/internal/daemon/runtime_parity_test.go index 834ee8911..65398f35a 100644 --- a/internal/daemon/runtime_parity_test.go +++ b/internal/daemon/runtime_parity_test.go @@ -87,7 +87,8 @@ func TestRuntimeRegistryEveryOperationOverUnixRPC(t *testing.T) { if _, err := store.AddSchedule(rootID, "@every 10m", "existing", time.Now().UTC().Add(time.Hour)); err != nil { t.Fatal(err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { components := Components{Runner: &controlSurfaceRunner{fakeRunner: &fakeRunner{}, workingDirectory: home}, MCP: &controlSurfaceMCP{}} if operation.Name == "mcp.refresh" { components.MCP = nil diff --git a/internal/daemon/scheduler_test.go b/internal/daemon/scheduler_test.go index a2de2e484..a6a64a4dc 100644 --- a/internal/daemon/scheduler_test.go +++ b/internal/daemon/scheduler_test.go @@ -49,7 +49,8 @@ func TestSchedulerClaimsDueFireWithoutClient(t *testing.T) { fired <- authored return "done", nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/server_test.go b/internal/daemon/server_test.go index 1e82e4872..b8ef6c333 100644 --- a/internal/daemon/server_test.go +++ b/internal/daemon/server_test.go @@ -38,7 +38,8 @@ func TestServerServesWithUnresumableSessionAndRecoversAfterRepair(t *testing.T) if _, err := store.AddSchedule(rootID, "@every 1h", "wake", time.Now()); err != nil { t.Fatal(err) } - value, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { current, err := config.Load() if err != nil { return Components{}, err @@ -114,7 +115,8 @@ func TestProviderValidationIsEphemeralAndNeverCreatesACommand(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -150,7 +152,8 @@ func TestProtocolClientCommandReplayAndSnapshot(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -237,7 +240,8 @@ func TestProtocolAllowsConcurrentPrincipalConnectionsAndRejectsOversizedFrame(t t.Fatal("nil daemon server was created") } store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -285,7 +289,8 @@ func TestProtocolAllowsConcurrentPrincipalConnectionsAndRejectsOversizedFrame(t func TestProtocolRejectsMalformedInitialization(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -338,7 +343,8 @@ func (*failingListener) Addr() net.Addr { return &net.TCPAddr{} } func TestServerServeReportsListenerFailureAndHonorsPreClose(t *testing.T) { newValue := func(path string) *Daemon { store := openStore(t, path) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -372,7 +378,8 @@ func TestServerServeReportsListenerFailureAndHonorsPreClose(t *testing.T) { func TestProtocolHandlersRejectMalformedParameters(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -400,7 +407,8 @@ func TestProtocolHandlersRejectMalformedParameters(t *testing.T) { func TestServerReportsClosedStoreAndEncodingFailures(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -410,6 +418,9 @@ func TestServerReportsClosedStoreAndEncodingFailures(t *testing.T) { if err != nil { t.Fatal(err) } + if err := processes.Close(); err != nil { + t.Fatal(err) + } if err := store.Close(); err != nil { t.Fatal(err) } @@ -430,7 +441,8 @@ func TestProtocolBoundsInitializationConnectionsAndInFlightWork(t *testing.T) { rootID := createRoot(t, store) started := make(chan struct{}) release := make(chan struct{}) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{turn: func(context.Context, string, bool) (string, error) { close(started) <-release @@ -523,7 +535,8 @@ func TestProtocolBoundsInitializationConnectionsAndInFlightWork(t *testing.T) { func TestInitializedIdleConnectionExpiresAndReleasesItsSlot(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -579,7 +592,8 @@ func TestInitializedIdleConnectionExpiresAndReleasesItsSlot(t *testing.T) { func TestSlowOutboundClientClosesWithoutStoppingDaemon(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -622,7 +636,8 @@ func TestSlowOutboundClientClosesWithoutStoppingDaemon(t *testing.T) { func TestOutboundQueueOverflowClosesConnection(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -657,7 +672,8 @@ func TestSnapshotBoundsLargeHistoryAndPagesContentReferences(t *testing.T) { if err := store.Save(rootID, 0, []llm.Message{{Role: "system", Content: "system"}, {Role: "user", Content: large}}, "model", "provider"); err != nil { t.Fatal(err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -705,7 +721,8 @@ func TestSnapshotBoundsLargeHistoryAndPagesContentReferences(t *testing.T) { func TestServerCommandValidation(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/session.go b/internal/daemon/session.go index c9c25dc9f..60bc5634f 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -286,6 +286,7 @@ type Session struct { titleChanged func(string) providers *providersvc.ProviderService store *sessionstore.Store + processes *capability.ProcessManager // borrowed from the daemon; roots stop only their scope // Identity is fixed for the root's lifetime. Saved facts (title, goal, // archive state, directory) are read from the store when a decision needs // them; nothing here mirrors the sessions row. @@ -356,13 +357,13 @@ type runConfiguration struct { cacheKey string } -func newSession(store *sessionstore.Store, meta sessionstore.Meta, authority capability.Authority, components Components, factories ...Factory) *Session { +func newSession(store *sessionstore.Store, processes *capability.ProcessManager, meta sessionstore.Meta, authority capability.Authority, components Components, factories ...Factory) *Session { goalMax := components.GoalMaxRounds if goalMax <= 0 { goalMax = config.DefaultGoalMaxRounds } root := &Session{ - store: store, id: meta.ID, kind: meta.Kind, engine: meta.ExecutionEngine, definitionRevision: meta.DefinitionRevision, + store: store, processes: processes, id: meta.ID, kind: meta.Kind, engine: meta.ExecutionEngine, definitionRevision: meta.DefinitionRevision, model: meta.Model, provider: meta.Provider, effort: meta.Effort, authority: authority, definition: effectiveDefinition(components), runner: components.Runner, mcp: components.MCP, loadMCP: components.LoadMCP, mcpServers: slices.Clone(effectiveDefinition(components).MCP.Servers), runtime: components.Runtime, supervisor: newSupervisor(), mailbox: make(chan inboxReady, 1), done: make(chan struct{}), receipts: make(map[int64][]*Receipt), goalMax: goalMax, @@ -667,7 +668,7 @@ func (s *Session) run() { if s.runtime != nil { cleanupErr = errors.Join(cleanupErr, safeClose("runtime", s.runtime.Close)) } - cleanupErr = errors.Join(cleanupErr, s.store.Processes().StopRoot(s.id)) + cleanupErr = errors.Join(cleanupErr, s.processes.StopRoot(s.id)) // Settle control calls that were admitted before stopping. Some of those // callers are supervised workers, so waiting for workers first would leave // each side waiting on the other. diff --git a/internal/daemon/session_metadata_test.go b/internal/daemon/session_metadata_test.go index 1366f8737..ced2a6ee0 100644 --- a/internal/daemon/session_metadata_test.go +++ b/internal/daemon/session_metadata_test.go @@ -52,7 +52,8 @@ func TestSessionMetadataDoesNotOpenRuntime(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) opens := 0 - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { opens++ return Components{Runner: &fakeRunner{}}, nil }) diff --git a/internal/daemon/session_state_ownership_test.go b/internal/daemon/session_state_ownership_test.go index b4ec67c53..cf1e794fc 100644 --- a/internal/daemon/session_state_ownership_test.go +++ b/internal/daemon/session_state_ownership_test.go @@ -21,7 +21,8 @@ func TestEffortPersistsBeforeItApplies(t *testing.T) { store := openStore(t, path) rootID := createRoot(t, store) runner := &controlSurfaceRunner{fakeRunner: &fakeRunner{}} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -80,7 +81,8 @@ func TestGoalCommandsRefuseWhileGoalFormulationRuns(t *testing.T) { fakeRunner: &fakeRunner{turn: func(context.Context, string, bool) (string, error) { return "GOAL_MET — verified", nil }}, started: make(chan struct{}), release: make(chan struct{}), } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/session_summaries_test.go b/internal/daemon/session_summaries_test.go index 972966ad9..8225a7823 100644 --- a/internal/daemon/session_summaries_test.go +++ b/internal/daemon/session_summaries_test.go @@ -84,7 +84,8 @@ func TestSessionSummariesAcrossTransports(t *testing.T) { func TestSessionSummariesDoNotOpenRootsAndObserveConcurrentQuestionAnswers(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) opens := 0 - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { opens++ return Components{Runner: &fakeRunner{}}, nil }) diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index 52011c67d..1962feea7 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -131,6 +131,14 @@ func (l *panicLifecycle) Start(context.Context) { l.launcher("MCP lifecycle", func() { panic("MCP exploded") }) } +// newTestProcesses retains caller cleanup if construction fails; successful owners close it first. +func newTestProcesses(t *testing.T) *capability.ProcessManager { + t.Helper() + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) + return processes +} + func openStore(t *testing.T, path string) *session.Store { t.Helper() store, err := session.Open(path) @@ -165,7 +173,8 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &titleRunner{fakeRunner: &fakeRunner{}, title: "Worker Queue Investigation", finished: make(chan struct{})} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -215,7 +224,8 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &titleRunner{fakeRunner: &fakeRunner{}, title: "Unicode Session Title", finished: make(chan struct{})} - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -257,7 +267,8 @@ func TestAutomaticTitlePublishesUpdateAndCannotOverwriteRename(t *testing.T) { fakeRunner: &fakeRunner{}, title: "Generated Too Late", started: make(chan struct{}), release: make(chan struct{}), finished: make(chan struct{}), } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -309,7 +320,8 @@ func TestConcurrentSubmitUsesCommittedInboxOrder(t *testing.T) { mu.Unlock() return "done " + input, nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -387,7 +399,8 @@ func TestRootsRunConcurrentlyAndCallerCancellationDoesNotOwnWork(t *testing.T) { } }} } - daemon, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { runners[meta.ID].history = append([]llm.Message(nil), history...) return Components{Runner: runners[meta.ID]}, nil }) @@ -436,7 +449,8 @@ func TestUnobservedCompletionCannotBlockActor(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -460,7 +474,8 @@ func TestSteerWhileIdleRunsAsAuthoredTurn(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) runner := &fakeRunner{} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -499,7 +514,8 @@ func TestSteerDuringTurnRunsAsNextTurn(t *testing.T) { } return input, nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -531,7 +547,8 @@ func TestReturnedTurnErrorIsRecoverable(t *testing.T) { } return "recovered", nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -577,7 +594,8 @@ func TestGoalContinuationRunsWithoutClientAndClearsGoal(t *testing.T) { continued <- authored return "GOAL_MET - verified", nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner, GoalMaxRounds: 2}, nil }) if err != nil { @@ -626,7 +644,8 @@ func TestWorkerAndActorPanicsAreRootLocalAndAwaitCleanup(t *testing.T) { badID, goodID := createRoot(t, store), createRoot(t, store) goodRunner := &fakeRunner{} mcp := &fakeCloser{} - daemon, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { if meta.ID == badID { return Components{Runner: test.runner, MCP: mcp}, nil } @@ -651,7 +670,7 @@ func TestWorkerAndActorPanicsAreRootLocalAndAwaitCleanup(t *testing.T) { } <-descendantStarted processStopped := make(chan struct{}) - unregister, err := store.Processes().RegisterStop(badID, func() error { + unregister, err := processes.RegisterStop(badID, func() error { close(processStopped) return nil }) @@ -699,7 +718,8 @@ func TestMCPLifecyclePanicFailsOnlyItsRoot(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) badID, goodID := createRoot(t, store), createRoot(t, store) lifecycle := &panicLifecycle{} - daemon, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { if meta.ID == badID { return Components{Runner: &fakeRunner{}, MCP: lifecycle}, nil } @@ -749,7 +769,8 @@ func TestToolPanicReentersRootSupervisor(t *testing.T) { Def: llm.NewTool("explode", "panic", `{"type":"object"}`), Run: func(context.Context, json.RawMessage) (string, error) { panic("tool exploded") }, }) - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &AgentSession{agent: ag}, Definition: withoutAutomaticTitle()}, nil }) if err != nil { @@ -789,7 +810,8 @@ func TestAgentStreamEventsAreDurableOrderedAndSnapshotRestorable(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) agentValue := agent.NewRuntime(llm.New(server.URL, "key"), "model", 100, "system", tools.NewServices()) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &AgentSession{agent: agentValue}, Definition: withoutAutomaticTitle()}, nil }) if err != nil { @@ -869,7 +891,8 @@ func TestOpenBindsMCPProcesses(t *testing.T) { rootID := createRoot(t, store) ag := agent.NewRuntime(llm.New("http://unused", "key"), "model", 100, "system", tools.NewServices()) manager := &fakeMCP{} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &AgentSession{agent: ag}, MCP: manager, Definition: withoutAutomaticTitle()}, nil }) if err != nil { @@ -880,10 +903,10 @@ func TestOpenBindsMCPProcesses(t *testing.T) { if err != nil { t.Fatal(err) } - if manager.processes != store.Processes() || manager.rootID != rootID || manager.cwd != root.WorkingDirectory() { + if manager.processes != processes || manager.rootID != rootID || manager.cwd != root.WorkingDirectory() { t.Fatalf("MCP process scope=%p %q %q", manager.processes, manager.rootID, manager.cwd) } - if options := ag.Services.ProcessOptions(); options.Processes != store.Processes() || options.RootID != rootID { + if options := ag.Services.ProcessOptions(); options.Processes != processes || options.RootID != rootID { t.Fatalf("agent process scope = %p %q", options.Processes, options.RootID) } if len(ag.AllTools()) != 0 { @@ -902,7 +925,8 @@ func TestStopAwaitsWorkerAndUnblocksReceipt(t *testing.T) { close(exited) return "", ctx.Err() }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -945,7 +969,8 @@ func TestOpenSharesLiveRootWithoutHoldingRegistryLockDuringFactory(t *testing.T) slowFactoryEntered := make(chan struct{}) releaseSlowFactory := make(chan struct{}) var calls atomic.Int32 - daemon, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { calls.Add(1) if meta.ID == slowID { close(slowFactoryEntered) @@ -1016,7 +1041,8 @@ func TestDispatchWaitsForAdmissionPublication(t *testing.T) { }); err != nil { t.Fatal(err) } - root := newSession(store, meta, authority, Components{Runner: &fakeRunner{}}) + processes := newTestProcesses(t) + root := newSession(store, processes, meta, authority, Components{Runner: &fakeRunner{}}) t.Cleanup(root.supervisor.stop) root.admitMu.RLock() dispatched := make(chan error, 1) @@ -1040,7 +1066,8 @@ func TestOpenCanonicalizesAliasesAndReportsStoppedRoots(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) var calls atomic.Int32 - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { calls.Add(1) return Components{Runner: &fakeRunner{}}, nil }) @@ -1072,7 +1099,8 @@ func TestResumeActiveOpensDurableRootsAndReportsFailures(t *testing.T) { t.Fatal(err) } var opened atomic.Int32 - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { opened.Add(1) return Components{Runner: &fakeRunner{}}, nil }) @@ -1087,12 +1115,16 @@ func TestResumeActiveOpensDurableRootsAndReportsFailures(t *testing.T) { } closedStore := openStore(t, filepath.Join(t.TempDir(), "closed-active.db")) - closed, err := New(closedStore, func(context.Context, session.Meta, []llm.Message) (Components, error) { + closedStoreProcesses := newTestProcesses(t) + closed, err := New(closedStore, closedStoreProcesses, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { t.Fatal(err) } + if err := closedStoreProcesses.Close(); err != nil { + t.Fatal(err) + } if err := closedStore.Close(); err != nil { t.Fatal(err) } @@ -1148,11 +1180,15 @@ func TestSessionWakeAndReferencedInboxFailuresAreReported(t *testing.T) { if err != nil || len(items) != 1 || items[0].Seq != sequence.InboxSeq { t.Fatalf("referenced inbox = %+v, %v", items, err) } - root := newSession(store, meta, authority, Components{Runner: &fakeRunner{}}) + processes := newTestProcesses(t) + root := newSession(store, processes, meta, authority, Components{Runner: &fakeRunner{}}) text, err := root.inboxText(items[0]) if err != nil || text != large { t.Fatalf("resolved inbox = %d bytes, %v", len(text), err) } + if err := processes.Close(); err != nil { + t.Fatal(err) + } if err := store.Close(); err != nil { t.Fatal(err) } @@ -1178,7 +1214,8 @@ func TestAgentRunnerSafeCloseEdges(t *testing.T) { func TestFactoryPanicSettlesOpenAndClose(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { panic("factory exploded") }) if err != nil { @@ -1203,14 +1240,18 @@ func TestNewAndOpenValidateAndCleanUpFailedConstruction(t *testing.T) { factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil } - if _, err := New(nil, factory); err == nil { + if _, err := New(nil, nil, factory); err == nil { t.Fatal("nil store was accepted") } closedStore := openStore(t, filepath.Join(t.TempDir(), "closed.db")) + closedStoreProcesses := newTestProcesses(t) + if err := closedStoreProcesses.Close(); err != nil { + t.Fatal(err) + } if err := closedStore.Close(); err != nil { t.Fatal(err) } - if _, err := New(closedStore, factory); err == nil { + if _, err := New(closedStore, closedStoreProcesses, factory); err == nil { t.Fatal("closed store recovery succeeded") } if !closedStore.AcquireDaemon() { @@ -1218,7 +1259,8 @@ func TestNewAndOpenValidateAndCleanUpFailedConstruction(t *testing.T) { } closedStore.ReleaseDaemon() store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - if _, err := New(store, nil); err == nil { + processes := newTestProcesses(t) + if _, err := New(store, processes, nil); err == nil { t.Fatal("nil factory was accepted") } bindRootID, missingRunnerRootID := createRoot(t, store), createRoot(t, store) @@ -1226,14 +1268,14 @@ func TestNewAndOpenValidateAndCleanUpFailedConstruction(t *testing.T) { runner := &bindErrorRunner{err: bindErr} bindMCP, missingRunnerMCP := &fakeCloser{}, &fakeCloser{} var bindProcessStopped, missingRunnerProcessStopped atomic.Bool - daemon, err := New(store, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { + daemon, err := New(store, processes, func(_ context.Context, meta session.Meta, _ []llm.Message) (Components, error) { stopped := &bindProcessStopped components := Components{Runner: runner, MCP: bindMCP} if meta.ID == missingRunnerRootID { stopped = &missingRunnerProcessStopped components = Components{MCP: missingRunnerMCP} } - if _, err := store.Processes().RegisterStop(meta.ID, func() error { + if _, err := processes.RegisterStop(meta.ID, func() error { stopped.Store(true) return nil }); err != nil { @@ -1272,7 +1314,8 @@ func TestCloseCancelsInFlightFactory(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) entered := make(chan struct{}) - daemon, err := New(store, func(ctx context.Context, _ session.Meta, _ []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(ctx context.Context, _ session.Meta, _ []llm.Message) (Components, error) { close(entered) <-ctx.Done() return Components{}, ctx.Err() @@ -1374,18 +1417,19 @@ func TestNewRejectsSecondDaemonOwner(t *testing.T) { factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil } - daemon, err := New(store, factory) + processes := newTestProcesses(t) + daemon, err := New(store, processes, factory) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = daemon.Close() }) - if _, err := New(store, factory); err == nil || !strings.Contains(err.Error(), "already has a daemon owner") { + if _, err := New(store, processes, factory); err == nil || !strings.Contains(err.Error(), "already has a daemon owner") { t.Fatalf("second daemon error=%v", err) } if _, err := store.LoadMeta(createRoot(t, store)); err != nil { t.Fatalf("second-owner rejection closed the database: %v", err) } - unregister, err := store.Processes().RegisterStop("after-second-owner-rejection", func() error { return nil }) + unregister, err := processes.RegisterStop("after-second-owner-rejection", func() error { return nil }) if err != nil { t.Fatalf("second-owner rejection closed the process manager: %v", err) } @@ -1404,7 +1448,8 @@ func TestClosePreservesClaimedScheduleWake(t *testing.T) { return "", ctx.Err() }, } - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { @@ -1466,7 +1511,8 @@ func TestReopenReconstructsHistoryAndRunsQueuedSubmitOnce(t *testing.T) { store = openStore(t, path) runner := &fakeRunner{} var restored []llm.Message - daemon, err := New(store, func(_ context.Context, _ session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(_ context.Context, _ session.Meta, history []llm.Message) (Components, error) { restored = append([]llm.Message(nil), history...) runner.history = append([]llm.Message(nil), history...) return Components{Runner: runner}, nil @@ -1531,7 +1577,8 @@ func TestReopenResumesQueuedScheduleAsUnauthored(t *testing.T) { started <- authored return "done", nil }} - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/state_test.go b/internal/daemon/state_test.go index 5f6a0cd63..e6eb152ab 100644 --- a/internal/daemon/state_test.go +++ b/internal/daemon/state_test.go @@ -14,7 +14,8 @@ import ( func TestStateWrappersRouteThroughActor(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) - daemon, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + daemon, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -77,7 +78,8 @@ func TestBlackboardSubscriptionRoutesThroughActorAndSurvivesRecovery(t *testing. factory := func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil } - daemon, err := New(store, factory) + processes := newTestProcesses(t) + daemon, err := New(store, processes, factory) if err != nil { t.Fatal(err) } @@ -121,7 +123,8 @@ func TestBlackboardSubscriptionRoutesThroughActorAndSurvivesRecovery(t *testing. } store = openStore(t, path) - daemon, err = New(store, factory) + processes = newTestProcesses(t) + daemon, err = New(store, processes, factory) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/subscription_runtime_test.go b/internal/daemon/subscription_runtime_test.go index a8fea9544..04d450e8f 100644 --- a/internal/daemon/subscription_runtime_test.go +++ b/internal/daemon/subscription_runtime_test.go @@ -97,7 +97,8 @@ func TestSubscriptionRecursiveRuntimeToolsHelpersTitleAndCompaction(t *testing.T store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) rootID := createRoot(t, store) var runtime *RecursiveRuntime - owner, err := New(store, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(_ context.Context, meta session.Meta, history []llm.Message) (Components, error) { value := agent.NewRuntime(client, "gpt-5.5", llm.SubscriptionOutputLimit("gpt-5.5"), "", tools.NewServices()) value.ModelName, value.Provider, value.WorkingDir = "gpt-5.5", openaiauth.Provider, meta.CWD value.ContextLimit = 400000 diff --git a/internal/daemon/terminal_rpc_test.go b/internal/daemon/terminal_rpc_test.go index eb1296ca1..4f7d1682a 100644 --- a/internal/daemon/terminal_rpc_test.go +++ b/internal/daemon/terminal_rpc_test.go @@ -19,7 +19,8 @@ func terminalTestServer(t *testing.T, networkTerminals bool) *Server { t.Helper() t.Setenv("SHELL", "/bin/sh") store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/title_lifecycle_test.go b/internal/daemon/title_lifecycle_test.go index 66934d594..a3a647ac1 100644 --- a/internal/daemon/title_lifecycle_test.go +++ b/internal/daemon/title_lifecycle_test.go @@ -33,7 +33,8 @@ func (r *lifecycleTitleRunner) GenerateTitle(ctx context.Context, prompt string) func openTitleLifecycle(t *testing.T, store *session.Store, rootID string, runner Runner) (*Daemon, *Session) { t.Helper() - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/title_notifications_test.go b/internal/daemon/title_notifications_test.go index c39236ded..12cfc779b 100644 --- a/internal/daemon/title_notifications_test.go +++ b/internal/daemon/title_notifications_test.go @@ -21,7 +21,8 @@ import ( func titleNotificationServer(t *testing.T, options ServerOptions) (*Daemon, *Server) { t.Helper() store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { @@ -495,7 +496,8 @@ func TestTitleNotificationsColdRenameCommitAndFailure(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, path) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { t.Error("cold rename reconstructed a root") return Components{}, errors.New("unavailable workspace") }) diff --git a/internal/daemon/tool_runner.go b/internal/daemon/tool_runner.go index f82d8fcc5..0edbdf516 100644 --- a/internal/daemon/tool_runner.go +++ b/internal/daemon/tool_runner.go @@ -35,7 +35,7 @@ func (r *toolRunner) bind(root *Session) error { } return value.ReferenceID, nil }) - return r.services.BindDispatcher(root.store, root.store.Workspaces(), root.store.Processes(), root.authority) + return r.services.BindDispatcher(root.store, root.store.Workspaces(), root.processes, root.authority) } func (*toolRunner) Turn(context.Context, string, bool, func(), func(string)) (string, error) { diff --git a/internal/daemon/tools_test.go b/internal/daemon/tools_test.go index 66dc8a459..5e7e4d3d6 100644 --- a/internal/daemon/tools_test.go +++ b/internal/daemon/tools_test.go @@ -386,7 +386,8 @@ func TestExecutorBindValidatesDefinitionAndHandlers(t *testing.T) { if err != nil || len(tools) != 0 || !slices.Equal(hooks, []string{"before_tool", "turn_start"}) { t.Fatalf("hook coverage = %v %v %v", tools, hooks, err) } - value, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + value, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: &fakeRunner{}}, nil }) if err != nil { diff --git a/internal/daemon/trace_rpc_test.go b/internal/daemon/trace_rpc_test.go index 21ea62479..32434c90d 100644 --- a/internal/daemon/trace_rpc_test.go +++ b/internal/daemon/trace_rpc_test.go @@ -148,7 +148,7 @@ func TestTracePageBoundsWireBytesAndKeepsConnection(t *testing.T) { func TestTracePageAfterReopenDoesNotOpenRuntime(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, path) - defer store.Close() + t.Cleanup(func() { _ = store.Close() }) root := createRoot(t, store) emptyRoot := createRoot(t, store) start := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano() @@ -174,11 +174,13 @@ func TestTracePageAfterReopenDoesNotOpenRuntime(t *testing.T) { } store = openStore(t, path) opens := 0 - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { opens++ return Components{Runner: &fakeRunner{}}, nil }) if err != nil { + _ = processes.Close() _ = store.Close() t.Fatal(err) } diff --git a/internal/daemon/v2_acceptance_test.go b/internal/daemon/v2_acceptance_test.go index c39c60975..1a64a6601 100644 --- a/internal/daemon/v2_acceptance_test.go +++ b/internal/daemon/v2_acceptance_test.go @@ -32,7 +32,8 @@ func newV2Fixture(t *testing.T, runner Runner, origins ...string) v2Fixture { } store := openStore(t, filepath.Join(paths.Home, "sessions.db")) rootID := createRoot(t, store) - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/v2_crash_test.go b/internal/daemon/v2_crash_test.go index 45e2fd2a9..33797738c 100644 --- a/internal/daemon/v2_crash_test.go +++ b/internal/daemon/v2_crash_test.go @@ -153,7 +153,8 @@ func serveCrashFixture(t *testing.T, home string, store *session.Store, rootID s if err != nil { t.Fatal(err) } - owner, err := New(store, func(context.Context, session.Meta, []llm.Message) (Components, error) { + processes := newTestProcesses(t) + owner, err := New(store, processes, func(context.Context, session.Meta, []llm.Message) (Components, error) { return Components{Runner: runner}, nil }) if err != nil { diff --git a/internal/daemon/v2_sdk_test.go b/internal/daemon/v2_sdk_test.go index c63c03d92..3ab27ae8d 100644 --- a/internal/daemon/v2_sdk_test.go +++ b/internal/daemon/v2_sdk_test.go @@ -136,7 +136,7 @@ func TestV2SDKBridge(t *testing.T) { } return Components{Runner: value, Bind: func(_ context.Context, root *Session) error { value.root = root - return value.services.BindDispatcher(root.store, root.store.Workspaces(), root.store.Processes(), root.authority) + return value.services.BindDispatcher(root.store, root.store.Workspaces(), root.processes, root.authority) }}, nil } if os.Getenv("WHIP_SDK_AGENTS_FIXTURE") == "1" { @@ -146,7 +146,8 @@ func TestV2SDKBridge(t *testing.T) { factory, closeModel = sdkAgentsFactory(store) defer closeModel() } - owner, err := New(store, factory) + processes := newTestProcesses(t) + owner, err := New(store, processes, factory) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/workspace_test.go b/internal/daemon/workspace_test.go index 4a1f8cb15..3b62a7e5e 100644 --- a/internal/daemon/workspace_test.go +++ b/internal/daemon/workspace_test.go @@ -36,7 +36,9 @@ func TestAgentRunnerWorkspaceSnapshotsUseRootManagedProcesses(t *testing.T) { t.Fatal(err) } services := tools.NewServices() - if err := services.BindDispatcher(store, store.Workspaces(), store.Processes(), authority); err != nil { + processes := newTestProcesses(t) + t.Cleanup(services.Close) + if err := services.BindDispatcher(store, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } agentValue := agent.NewRuntime(llm.New("http://unused.invalid", ""), "model", 100, "system", tools.NewServices()) @@ -87,7 +89,9 @@ func TestWorkspaceSnapshotsIgnoreNonGitDirectoriesAndInvalidReferences(t *testin t.Fatal(err) } services := tools.NewServices() - if err := services.BindDispatcher(store, store.Workspaces(), store.Processes(), authority); err != nil { + processes := newTestProcesses(t) + t.Cleanup(services.Close) + if err := services.BindDispatcher(store, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } meta, _, err := store.Load(rootID) diff --git a/internal/mcp/serve_test.go b/internal/mcp/serve_test.go index 1c305a76a..61f1605a8 100644 --- a/internal/mcp/serve_test.go +++ b/internal/mcp/serve_test.go @@ -12,6 +12,7 @@ import ( sdkmcp "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/context-labs/whip/internal/browser" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" ) @@ -27,6 +28,8 @@ func TestServeInProcess(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) cwd, err := os.Getwd() if err != nil { t.Fatal(err) @@ -40,7 +43,7 @@ func TestServeInProcess(t *testing.T) { t.Fatal(err) } services := tools.NewServices() - if err := services.BindDispatcher(store, store.Workspaces(), store.Processes(), authority); err != nil { + if err := services.BindDispatcher(store, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } t.Cleanup(services.Close) diff --git a/internal/session/capability.go b/internal/session/capability.go index f2be37acc..1e943686f 100644 --- a/internal/session/capability.go +++ b/internal/session/capability.go @@ -33,8 +33,6 @@ type storedCapabilityScopes struct { func (s *Store) Workspaces() *capability.Workspaces { return s.workspaces } -func (s *Store) Processes() *capability.ProcessManager { return s.processes } - // EnsureAuthority installs the root agent and its initial grants once. // EnsureAuthority bootstraps or reloads a root with full grants: every file, // shell, and MCP operation. diff --git a/internal/session/capability_test.go b/internal/session/capability_test.go index ff9c6de26..1ede6333b 100644 --- a/internal/session/capability_test.go +++ b/internal/session/capability_test.go @@ -549,9 +549,6 @@ func TestCapabilityValidationCorruptionAndRollbackPaths(t *testing.T) { t.Run("accessors and bootstrap", func(t *testing.T) { st, rootID, agentID := actorFailureFixture(t) - if st.Processes() == nil { - t.Fatal("process manager is nil") - } if _, err := st.WorkspaceRoot(ctx, "missing"); err == nil { t.Fatal("missing workspace root was accepted") } diff --git a/internal/session/session.go b/internal/session/session.go index e9f7ae520..d33b31ff2 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -63,7 +63,6 @@ type Store struct { db *sql.DB content *contentstore.Store workspaces *capability.Workspaces - processes *capability.ProcessManager daemonOwned atomic.Bool globalRules atomic.Pointer[[]string] // config permissions.allow, "operation:rule" entries } @@ -108,7 +107,7 @@ func Open(path string) (*Store, error) { } store := &Store{ db: db, content: content, - workspaces: capability.NewWorkspaces(), processes: capability.NewProcessManager(), + workspaces: capability.NewWorkspaces(), } failed = false return store, nil @@ -168,7 +167,7 @@ func (s *Store) SetUsage(id string, in, cached, out int) error { return err } -func (s *Store) Close() error { return errors.Join(s.processes.Close(), s.db.Close()) } +func (s *Store) Close() error { return s.db.Close() } // stampLayout is RFC 3339 with a fixed nine-digit fraction: stored stamps // keep nanoseconds, sort lexicographically as text, and still parse with diff --git a/internal/tools/browser_desktop_boundaries_test.go b/internal/tools/browser_desktop_boundaries_test.go index 08c6b23b0..4d6742cb9 100644 --- a/internal/tools/browser_desktop_boundaries_test.go +++ b/internal/tools/browser_desktop_boundaries_test.go @@ -116,7 +116,7 @@ func TestDesktopAttachmentHelpersDenyUnboundAndUnavailable(t *testing.T) { t.Fatal("unavailable provider must not transfer attachments") } authority.AgentID = "unrelated-child" - if err := s.BindDispatcher(ledger, provider.store.Workspaces(), provider.store.Processes(), authority); err != nil { + if err := s.BindDispatcher(ledger, provider.store.Workspaces(), s.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } if _, err := s.TransferDesktopAttachments(t.Context(), "child", []string{"copied"}); !errors.Is(err, capability.ErrDenied) { diff --git a/internal/tools/browser_desktop_test.go b/internal/tools/browser_desktop_test.go index bededdb1a..fe9eec601 100644 --- a/internal/tools/browser_desktop_test.go +++ b/internal/tools/browser_desktop_test.go @@ -43,7 +43,7 @@ func TestDesktopBrowserDiscoveryRequiresModuleButNoControlAdmission(t *testing.T t.Fatalf("discovery crossed admission boundary: %+v", result) } authority.AgentID = "unrelated-child" - if err := s.BindDispatcher(ledger, p.store.Workspaces(), p.store.Processes(), authority); err != nil { + if err := s.BindDispatcher(ledger, p.store.Workspaces(), s.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } result = callDesktop(t, s, "browser.list_tabs", "{}") @@ -121,6 +121,8 @@ func desktopTestServices(t *testing.T) (*Services, *countingLedger, *testDesktop t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) root, err := store.Create(session.SessionKindAgent, t.TempDir(), "model", "provider") if err != nil { t.Fatal(err) @@ -132,9 +134,10 @@ func desktopTestServices(t *testing.T) (*Services, *countingLedger, *testDesktop ledger := &countingLedger{Store: store} provider := &testDesktopProvider{store: store, lifetime: t.Context(), scope: capability.BrowserScope{ProviderID: "provider", ProviderEpoch: "epoch", TabID: "tab", TabGeneration: "tab-generation", ProfileID: "profile", AttachmentID: "attachment", AttachmentGeneration: "attachment-generation", Rights: []string{"create", "control"}}, backend: &fakeBackend{mode: browser.Mode("desktop"), eval: `"hello"`, shot: []byte("jpeg")}} services := NewServices() + t.Cleanup(services.Close) services.SetDesktopBrowserProvider(func() browser.DesktopProvider { return provider }) services.SetGate(func(context.Context, GateRequest) (GateDecision, string) { return GateAllowOnce, "" }) - if err := services.BindDispatcher(ledger, store.Workspaces(), store.Processes(), authority); err != nil { + if err := services.BindDispatcher(ledger, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } return services, ledger, provider, authority diff --git a/internal/tools/dispatcher_test.go b/internal/tools/dispatcher_test.go index fdfa989e2..7b9250fb6 100644 --- a/internal/tools/dispatcher_test.go +++ b/internal/tools/dispatcher_test.go @@ -46,6 +46,8 @@ func TestBoundToolsUseDispatcherWithoutChangingOutput(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = st.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) rootID, err := st.Create(session.SessionKindAgent, root, "m", "p") if err != nil { t.Fatal(err) @@ -57,12 +59,13 @@ func TestBoundToolsUseDispatcherWithoutChangingOutput(t *testing.T) { ledger := &countingLedger{Store: st} services := NewServices() + t.Cleanup(services.Close) services.SetGate(func(context.Context, GateRequest) (GateDecision, string) { return GateAllowOnce, "" }) - if err := services.BindDispatcher(ledger, st.Workspaces(), st.Processes(), authority); err != nil { + if err := services.BindDispatcher(ledger, st.Workspaces(), processes, authority); err != nil { t.Fatal(err) } dispatcher := services.dispatcher - if err := services.BindDispatcher(ledger, st.Workspaces(), st.Processes(), authority); err != nil { + if err := services.BindDispatcher(ledger, st.Workspaces(), processes, authority); err != nil { t.Fatal(err) } if services.dispatcher != dispatcher { @@ -153,6 +156,8 @@ func TestBoundHostCallsHaveDistinctOperationIDs(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) rootID, err := store.Create(session.SessionKindAgent, workspace, "model", "provider") if err != nil { t.Fatal(err) @@ -163,7 +168,8 @@ func TestBoundHostCallsHaveDistinctOperationIDs(t *testing.T) { } ledger := &countingLedger{Store: store} services := NewServices() - if err := services.BindDispatcher(ledger, store.Workspaces(), store.Processes(), authority); err != nil { + t.Cleanup(services.Close) + if err := services.BindDispatcher(ledger, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } ctx, err := WithTurnIdentity(t.Context(), "host-call-test") @@ -222,6 +228,8 @@ func TestAuthorityCloneKeepsHostIntegrationsAndPermissionMode(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) rootID, err := store.Create(session.SessionKindAgent, root, "model", "provider") if err != nil { t.Fatal(err) @@ -234,6 +242,7 @@ func TestAuthorityCloneKeepsHostIntegrationsAndPermissionMode(t *testing.T) { manager := browser.NewManager(browser.ModeHeadless) policy := computer.NewPolicy([]string{"Finder"}, nil, true) parent := NewServices() + t.Cleanup(parent.Close) parent.SetBrowser(manager, true) parent.SetComputerPolicy(policy) parent.SetComputerApprover(func(string) bool { return true }) @@ -241,10 +250,11 @@ func TestAuthorityCloneKeepsHostIntegrationsAndPermissionMode(t *testing.T) { parent.SetExternalPermissions(true) parent.noteGeneration("Finder", 7) - clone, err := parent.CloneForAuthority(store, store.Workspaces(), store.Processes(), authority) + clone, err := parent.CloneForAuthority(store, store.Workspaces(), processes, authority) if err != nil { t.Fatal(err) } + t.Cleanup(clone.Close) cloneBrowser, allowPrivate, screenshot := clone.browserConfig() clonePolicy, approver := clone.computerApproval() if cloneBrowser != manager || !allowPrivate || clonePolicy != policy || approver == nil { diff --git a/internal/tools/jobs_test.go b/internal/tools/jobs_test.go index cc93ce9a8..0eef30cf4 100644 --- a/internal/tools/jobs_test.go +++ b/internal/tools/jobs_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/session" ) @@ -18,6 +19,8 @@ func TestShellStartJobsAreOwnedCappedAndClosedWithServices(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = st.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) rootID, err := st.Create(session.SessionKindAgent, root, "m", "p") if err != nil { t.Fatal(err) @@ -28,7 +31,7 @@ func TestShellStartJobsAreOwnedCappedAndClosedWithServices(t *testing.T) { } services := NewServices() services.SetGate(func(context.Context, GateRequest) (GateDecision, string) { return GateAllowOnce, "" }) - if err := services.BindDispatcher(&countingLedger{Store: st}, st.Workspaces(), st.Processes(), authority); err != nil { + if err := services.BindDispatcher(&countingLedger{Store: st}, st.Workspaces(), processes, authority); err != nil { t.Fatal(err) } t.Cleanup(services.Close) diff --git a/internal/tools/mcp_permission_test.go b/internal/tools/mcp_permission_test.go index a238ad8e8..0ceb53e1d 100644 --- a/internal/tools/mcp_permission_test.go +++ b/internal/tools/mcp_permission_test.go @@ -28,7 +28,7 @@ func (l *pausedMCPDecisionLedger) Decide(ctx context.Context, admission capabili } func TestMCPLatePermissionDecisionsCannotOutliveInvocation(t *testing.T) { - _, ledger, provider, authority := newMCPServices(t) + boundServices, ledger, provider, authority := newMCPServices(t) paused := &pausedMCPDecisionLedger{ countingLedger: ledger, before: make(chan struct{}), commit: make(chan struct{}), @@ -40,9 +40,10 @@ func TestMCPLatePermissionDecisionsCannotOutliveInvocation(t *testing.T) { defer commit() defer finish() services := NewServices() + t.Cleanup(services.Close) services.SetExternalPermissions(true) services.SetMCPProvider(func() MCPProvider { return provider }) - if err := services.BindDispatcher(paused, ledger.Workspaces(), ledger.Processes(), authority); err != nil { + if err := services.BindDispatcher(paused, ledger.Workspaces(), boundServices.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(t.Context()) diff --git a/internal/tools/mcp_test.go b/internal/tools/mcp_test.go index 81ad77f72..7cb84fda5 100644 --- a/internal/tools/mcp_test.go +++ b/internal/tools/mcp_test.go @@ -71,6 +71,8 @@ func newMCPServices(t *testing.T) (*Services, *countingLedger, *testMCPProvider, t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) rootID, err := store.Create(session.SessionKindAgent, t.TempDir(), "model", "provider") if err != nil { t.Fatal(err) @@ -85,8 +87,9 @@ func newMCPServices(t *testing.T) (*Services, *countingLedger, *testMCPProvider, Generation: "connection-1", Source: "imported Claude config", }} services := NewServices() + t.Cleanup(services.Close) services.SetMCPProvider(func() MCPProvider { return provider }) - if err := services.BindDispatcher(ledger, store.Workspaces(), store.Processes(), authority); err != nil { + if err := services.BindDispatcher(ledger, store.Workspaces(), processes, authority); err != nil { t.Fatal(err) } return services, ledger, provider, authority @@ -311,10 +314,11 @@ func TestMCPChildWithoutCapabilityCannotCallTrustedTool(t *testing.T) { childAuthority := capability.Authority{ RootID: authority.RootID, AgentID: "reader", } - clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), ledger.Processes(), childAuthority) + clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), services.ProcessOptions().Processes, childAuthority) if err != nil { t.Fatal(err) } + t.Cleanup(clone.Close) if _, err := clone.InvokeMCP(t.Context(), "my-server", "write.raw", nil); !errors.Is(err, capability.ErrDenied) { t.Fatalf("child lacking MCP authority error=%v", err) } @@ -342,10 +346,11 @@ func TestMCPOnlyRestoredAuthorityBindsWithoutLocalGrants(t *testing.T) { if restored.Files.ID != "" || restored.Shell.ID != "" || restored.MCP.ID == "" { t.Fatalf("restored capability set=%+v", restored) } - clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), ledger.Processes(), restored) + clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), services.ProcessOptions().Processes, restored) if err != nil { t.Fatal(err) } + t.Cleanup(clone.Close) if _, err := clone.InvokeMCP(t.Context(), "my-server", "write.raw", nil); err != nil { t.Fatalf("restored MCP-only child call error=%v", err) } @@ -474,7 +479,7 @@ func (l *pausedMCPLedger) Begin(ctx context.Context, admission capability.Admiss func TestMCPGenerationRetirementDuringAdmission(t *testing.T) { for _, stage := range []string{"before begin", "permission persisted", "operation running"} { t.Run(stage, func(t *testing.T) { - _, ledger, provider, authority := newMCPServices(t) + boundServices, ledger, provider, authority := newMCPServices(t) provider.descriptor.Trusted = stage == "operation running" lifetime, retire := context.WithCancel(t.Context()) defer retire() @@ -484,9 +489,10 @@ func TestMCPGenerationRetirementDuringAdmission(t *testing.T) { entered: make(chan context.Context, 1), resume: make(chan struct{}), } services := NewServices() + t.Cleanup(services.Close) services.SetExternalPermissions(true) services.SetMCPProvider(func() MCPProvider { return provider }) - if err := services.BindDispatcher(paused, ledger.Workspaces(), ledger.Processes(), authority); err != nil { + if err := services.BindDispatcher(paused, ledger.Workspaces(), boundServices.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } result := make(chan error, 1) @@ -559,9 +565,10 @@ func TestMCPCopiedPermissionPolicyKeepsReplacementProvider(t *testing.T) { replacementProvider.descriptor.Generation = "replacement" replacementProvider.descriptor.Trusted = mode == "explicit denial" replacement := NewServices() + t.Cleanup(replacement.Close) replacement.SetMCPProvider(func() MCPProvider { return replacementProvider }) replacement.CopyPermissionPolicyFrom(previous) - if err := replacement.BindDispatcher(ledger, ledger.Workspaces(), ledger.Processes(), authority); err != nil { + if err := replacement.BindDispatcher(ledger, ledger.Workspaces(), previous.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } ctx, cancel := context.WithTimeout(t.Context(), time.Second) diff --git a/internal/tools/permission_test.go b/internal/tools/permission_test.go index bad7e021c..3b0e5e44e 100644 --- a/internal/tools/permission_test.go +++ b/internal/tools/permission_test.go @@ -200,7 +200,7 @@ func TestExternalPermissionDecisionClaimSurvivesHandoff(t *testing.T) { name = operation + "/allow" } t.Run(name, func(t *testing.T) { - _, ledger, provider, authority := newMCPServices(t) + boundServices, ledger, provider, authority := newMCPServices(t) paused := &pausedMCPDecisionLedger{ countingLedger: ledger, before: make(chan struct{}), commit: make(chan struct{}), @@ -212,9 +212,10 @@ func TestExternalPermissionDecisionClaimSurvivesHandoff(t *testing.T) { defer finish() defer commit() services := NewServices() + t.Cleanup(services.Close) services.SetExternalPermissions(true) services.SetMCPProvider(func() MCPProvider { return provider }) - if err := services.BindDispatcher(paused, ledger.Workspaces(), ledger.Processes(), authority); err != nil { + if err := services.BindDispatcher(paused, ledger.Workspaces(), boundServices.ProcessOptions().Processes, authority); err != nil { t.Fatal(err) } path := filepath.Join(services.ProcessOptions().Cwd, "decision.txt") diff --git a/internal/tools/tools_test.go b/internal/tools/tools_test.go index 14781ff59..7c15fe395 100644 --- a/internal/tools/tools_test.go +++ b/internal/tools/tools_test.go @@ -345,10 +345,11 @@ func TestWorkspaceProcessHonorsPermissionAndEnvironment(t *testing.T) { t.Fatalf("workspace process bypassed its authority: %+v", admission) } services.SetScreenshotSink(func([][]byte) { t.Error("parent screenshot sink reached a clone") }) - clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), ledger.Processes(), authority) + clone, err := services.CloneForAuthority(ledger, ledger.Workspaces(), services.ProcessOptions().Processes, authority) if err != nil { t.Fatal(err) } + t.Cleanup(clone.Close) if !services.ScreenshotsEnabled() || clone.ScreenshotsEnabled() { t.Fatal("authority clone inherited an agent-specific screenshot destination") } diff --git a/internal/tui/client_integration_test.go b/internal/tui/client_integration_test.go index 77e646f0c..e7d7aa96c 100644 --- a/internal/tui/client_integration_test.go +++ b/internal/tui/client_integration_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" @@ -47,7 +48,9 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = store.Close() }) - owner, err := daemon.New(store, func(context.Context, session.Meta, []llm.Message) (daemon.Components, error) { + processes := capability.NewProcessManager() + t.Cleanup(func() { _ = processes.Close() }) + owner, err := daemon.New(store, processes, func(context.Context, session.Meta, []llm.Message) (daemon.Components, error) { return daemon.Components{Runner: &startupRunner{}}, nil }) if err != nil { From 42285977df445ac79334ac96e465d44f057f0350 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:22:35 -0700 Subject: [PATCH 40/67] docs: record process ownership validation and parent provenance --- docs/backend-reorganization-plan.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 5b9c54c99..4f2c3b30b 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -672,11 +672,11 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Frozen-contract gate | `8f0230444eb447e87c619d7c689eca811ac5d1f3`, [PR #302](https://github.com/context-labs/whip/pull/302), based on PR #307. | Local fixed-reference and immediate-base comparisons passed, including mutation rejection and both-engine rollback. At historical head `a7be9a28a0f37598985733e2fe50e06af1aa06f4`, [CI](https://github.com/context-labs/whip/actions/runs/36681287828) passed both compatibility jobs, Go coverage, lint and runtime but failed the independently reproduced UI race. The new head includes the separate repair and has the exact previously green combined prerequisite tree. [Fresh CI](https://github.com/context-labs/whip/actions/runs/36686140019) remains pending. | | Host MCP ownership (plan PR 2) | `bfd030fb7bee920982c8d0ab9f6a4820be962166`, [PR #304](https://github.com/context-labs/whip/pull/304). | Three operation bodies move unchanged from `ProviderService` to a private `hostMCPService`, owned by `Server`. The original-implementation cancellation characterization, focused MCP/icon race tests, build/vet/whipvet, full daemon race/shuffle (250.722s), and fixed/immediate-base compatibility passed. Historical head `d8175212d3db3371b14862dc07ad24fc62393108` passed [full CI](https://github.com/context-labs/whip/actions/runs/36682214774) and security. Its tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686146852) is pending. | | Provider operation boundary (plan PR 3a) | `fec68225b2e6e888f138d2721c30d827987add73`, [PR #305](https://github.com/context-labs/whip/pull/305). | Catalog/reload characterization passed three times before extraction; typed catalog results, compaction validation, model admission and context borrowing retain their operation order. Local validation below was recorded at historical head `a211fb0e7629f9692eb5133aa00244aea17e38a9`. The complete tree is unchanged by reordering; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686153135) is pending. | -| Provider integration test boundary (plan PR 3b1) | `675717575868c5b3b9bf2da1a9b2863238b12a28`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686160171) is pending. | -| Provider package extraction (plan PR 3b2) | `355b792bc99567068e65fdd0fd9f992a5b50ea0c`, [PR #308](https://github.com/context-labs/whip/pull/308), based on PR #306. | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) and [security](https://github.com/context-labs/whip/actions/runs/36685870367) passed. | -| Startup factory extraction (plan PR 4a) | `13493cf20dd84c7c97a18d33b1a6202d849eae94`, [PR #309](https://github.com/context-labs/whip/pull/309), based on PR #308. | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. | -| Host directory grouping (plan PR 4b) | `0099a665221ba54ac23ca6656a8a1a017af6f48d`, [PR #310](https://github.com/context-labs/whip/pull/310), based on PR #309 (`13493cf20dd84c7c97a18d33b1a6202d849eae94`). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. | -| Process ownership (plan PR 5) | `codex/backend-reorg-05-process-ownership`, based on PR #310 (`0099a665221ba54ac23ca6656a8a1a017af6f48d`). | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | +| Provider integration test boundary (plan PR 3b1) | `cb959b12336d403ece55abd923afd09a4f98cc94`, [PR #306](https://github.com/context-labs/whip/pull/306). | Five integration tests use HTTP/auth persistence rather than private provider callbacks. At historical head `d81f814b139d3a2320db6942e02c22a3e54d9b80`, targeted race tests passed three times (23.256s), full daemon race/shuffle passed (261.125s), and build/vet/whipvet plus fresh fixed-SDK compatibility passed. The complete tree is unchanged; [fresh CI](https://github.com/context-labs/whip/actions/runs/36686160171) is pending. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | +| Provider package extraction (plan PR 3b2) | `4b5c0e5790f698371abed1ed4c8bcf3dd9cd3885`, [PR #308](https://github.com/context-labs/whip/pull/308). | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) and [security](https://github.com/context-labs/whip/actions/runs/36685870367) passed. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | +| Startup factory extraction (plan PR 4a) | `b251786c8d868cba722f103d0a77ce72d07377f5`, [PR #309](https://github.com/context-labs/whip/pull/309). | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | +| Host directory grouping (plan PR 4b) | `774623f12ef182856862209d186bc70150d17cf1`, [PR #310](https://github.com/context-labs/whip/pull/310). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | +| Process ownership (plan PR 5) | `057edb919da1a652fb284e2d54d4cf020a7867c6`, based on PR #310 (`774623f12ef182856862209d186bc70150d17cf1`). | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -947,3 +947,19 @@ narrow explained exception for the required cached-error identity comparison. Those two fixture cases passed again with race detection (1.916s). The inherited header correction belongs to PR3b1 and will arrive through the parent rebase; PR5 does not mix that repair into its ownership change. + +The inherited header fixture correction was committed in PR3b1, then rebased +through PR3b2/PR4a/PR4b/PR5. The final PR5 code head +`057edb919da1a652fb284e2d54d4cf020a7867c6` differs from the locally race-validated +`c339eba56b79ceb9dae78d95c2cb9892ab072bf9` only by that canonical spelling of the +same case-insensitive `Header.Get` key. The parent mapping is recorded at +`/private/tmp/whip-reorg-header-correction-rebase.json`. + +Final full golangci-lint 2.13.1 passed with zero issues. Fresh frozen compatibility +passed at the clean committed code head against immediate parent +`774623f12ef182856862209d186bc70150d17cf1`, with the fixed reference unchanged: +`/private/tmp/whip-pr5-published-compat-evidence/evidence.json`. The evidence has +an empty candidate diff and passes all calibrated transport/event, lifecycle, +mutation-rejection, and both-engine fixed/immediate-base rollback checks. This +recording update changes documentation only; hosted checks run on the published +PR head. The PR remains unmerged for review. From 1dcbacbb72c3ffda13938e21397e75e6e5bb7479 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:28:51 -0700 Subject: [PATCH 41/67] test(daemon): characterize shared workspace locks --- .../daemon/daemon_workspace_ownership_test.go | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 internal/daemon/daemon_workspace_ownership_test.go diff --git a/internal/daemon/daemon_workspace_ownership_test.go b/internal/daemon/daemon_workspace_ownership_test.go new file mode 100644 index 000000000..e929010c3 --- /dev/null +++ b/internal/daemon/daemon_workspace_ownership_test.go @@ -0,0 +1,200 @@ +package daemon + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "sync" + "testing" + "time" + + "github.com/context-labs/whip/internal/agent" + "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/rlm" + "github.com/context-labs/whip/internal/session" + "github.com/context-labs/whip/internal/tools" +) + +func TestWorkspaceCoordinatorIsSharedByRootsAndChildren(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + streamText(w, "done") + })) + t.Cleanup(server.Close) + client := llm.New(server.URL, "fixture-key") + client.MaxRetries = 0 + directory := canonicalPromptDirectory(t, t.TempDir()) + alias := filepath.Join(t.TempDir(), "workspace-alias") + if err := os.Symlink(directory, alias); err != nil { + t.Fatal(err) + } + database := filepath.Join(t.TempDir(), "sessions.db") + store := openStore(t, database) + ids := make([]string, 3) + for i, cwd := range []string{directory, alias, alias} { + kind := session.SessionKindAgent + model, provider := "model", "provider" + if i == 2 { + kind = session.SessionKindToolHost + model, provider = "", "" + } + id, err := store.Create(kind, cwd, model, provider) + if err != nil { + t.Fatal(err) + } + if err := store.SetPermissionMode(t.Context(), id, session.PermissionModeAutomatic); err != nil { + t.Fatal(err) + } + ids[i] = id + } + var childID string + for _, incarnation := range []string{"new child", "restored child"} { + t.Run(incarnation, func(t *testing.T) { + if incarnation == "restored child" { + store = openStore(t, database) + } + t.Cleanup(func() { _ = store.Close() }) + coordinator := store.Workspaces() + processes := newTestProcesses(t) + limits := rlm.DefaultLimits() + kernels := rlm.NewManager(limits.MaxWorkers) + t.Cleanup(kernels.Close) + runtimes := make(map[string]*RecursiveRuntime) + services := make(map[string]*tools.Services) + owner, err := New(store, processes, func(ctx context.Context, meta session.Meta, history []llm.Message) (Components, error) { + host := tools.NewServices() + services[meta.ID] = host + if meta.Kind == session.SessionKindToolHost { + return Components{Runner: NewToolRunner(host)}, nil + } + value := agent.NewRuntime(client, meta.Model, 128, "", host) + value.ModelName, value.Provider, value.WorkingDir = meta.Model, meta.Provider, meta.CWD + value.ContextLimit = 65536 + definition, _, err := DefinitionFor(ctx, store, meta) + if err != nil { + return Components{}, err + } + definition.Surface.AutoTitle = false + runtime, err := NewRecursiveRuntime(RecursiveRuntimeOptions{ + Engine: meta.ExecutionEngine, Definition: definition, Agent: value, History: history, + Limits: limits, Kernels: kernels, KernelCommand: recursiveKernelCommand, + }) + if err != nil { + return Components{}, err + } + runtimes[meta.ID] = runtime + return Components{Runner: runtime.RootSession(), Runtime: runtime, Bind: runtime.Bind, Definition: definition}, nil + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = owner.Close() }) + for _, id := range ids { + if _, err := owner.Open(id); err != nil { + t.Fatal(err) + } + } + runtime := runtimes[ids[0]] + if incarnation == "new child" { + runs := &sync.Map{} + runtime.setRunTurnHook(observeRunTurn(runs)) + spawned, err := runtime.rootNode.host.Call(t.Context(), "agents", "spawn", map[string]any{ + "name": "keeper", "prompt": "Finish immediately.", "report": "message", + }) + if err != nil { + t.Fatal(err) + } + childID = spawned.(map[string]any)["id"].(string) + waitRunTurn(t, runs, childID, 1) + } + runtime.mu.RLock() + child := runtime.agents[childID] + runtime.mu.RUnlock() + if child == nil { + t.Fatal("retained child is missing") + } + waitAgentIdle(t, child) + if store.Workspaces() != coordinator { + t.Fatal("runtime construction replaced the shared workspace coordinator") + } + assertSharedWorkspaceLocks(t, coordinator, directory, alias, []workspaceBorrower{ + {name: "first root", services: services[ids[0]], path: filepath.Join(directory, "target.txt")}, + {name: "second root", services: services[ids[1]], path: filepath.Join(alias, "target.txt")}, + {name: incarnation, services: child.agent.Services, path: filepath.Join(alias, "target.txt")}, + {name: "tool host", services: services[ids[2]], path: filepath.Join(alias, "target.txt")}, + }) + if err := owner.Close(); err != nil { + t.Fatal(err) + } + }) + } +} + +type workspaceBorrower struct { + name string + services *tools.Services + path string +} + +func assertSharedWorkspaceLocks(t *testing.T, coordinator *capability.Workspaces, directory, alias string, borrowers []workspaceBorrower) { + t.Helper() + write := func(ctx context.Context, borrower workspaceBorrower, path, content string) error { + ctx, err := tools.WithTurnIdentity(ctx, "workspace-ownership") + if err != nil { + return err + } + arguments, err := json.Marshal(map[string]string{"path": path, "content": content}) + if err != nil { + return err + } + _, err = borrower.services.Invoke(ctx, "write", arguments) + return err + } + for _, borrower := range borrowers { + if err := write(t.Context(), borrower, borrower.path, "before lock"); err != nil { + t.Fatalf("%s cannot write before locking: %v", borrower.name, err) + } + } + workspace, err := coordinator.Open(directory) + if err != nil { + t.Fatal(err) + } + _, release, err := workspace.LockCanonicalPath(t.Context(), filepath.Join(directory, "target.txt")) + if err != nil { + t.Fatal(err) + } + defer release() + for _, borrower := range borrowers { + t.Run(borrower.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(t.Context(), 500*time.Millisecond) + defer cancel() + if err := write(ctx, borrower, borrower.path, "must remain blocked"); !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("write did not wait on the shared canonical lock: %v", err) + } + if body, err := os.ReadFile(filepath.Join(directory, "target.txt")); err != nil || string(body) != "before lock" { + t.Fatalf("blocked write changed the target: %q, %v", body, err) + } + unrelated, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + if err := write(unrelated, borrower, filepath.Join(alias, "unrelated.txt"), borrower.name); err != nil { + t.Fatalf("unrelated path was blocked: %v", err) + } + }) + } + release() + for _, borrower := range borrowers { + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + err := write(ctx, borrower, borrower.path, borrower.name) + cancel() + if err != nil { + t.Fatalf("%s cannot write after release: %v", borrower.name, err) + } + if body, err := os.ReadFile(filepath.Join(directory, "target.txt")); err != nil || string(body) != borrower.name { + t.Fatalf("%s write after release = %q, %v", borrower.name, body, err) + } + } +} From 26a6fec9b505fd6c00cd10d64c753c779509a2a4 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:37:02 -0700 Subject: [PATCH 42/67] refactor(session): borrow host-owned workspace coordinator --- cmd/whip/daemon.go | 3 +- cmd/whip/daemon_client_test.go | 3 +- .../desktop_runtime_sync_integration_test.go | 5 +- cmd/whip/run_test.go | 9 ++- docs/backend-reorganization-plan.md | 74 ++++++++++++++++++- internal/agent/authority_test.go | 2 +- internal/daemon/acceptance_test.go | 5 +- internal/daemon/architecture_test.go | 7 +- internal/daemon/autostart_test.go | 2 +- .../daemon/daemon_workspace_ownership_test.go | 16 +++- internal/daemon/input_test.go | 2 +- internal/daemon/restart_test.go | 3 +- internal/daemon/session_test.go | 2 +- internal/daemon/v2_crash_test.go | 3 +- internal/mcp/serve_test.go | 2 +- internal/session/agent_report_test.go | 6 +- internal/session/browser_capability_test.go | 4 +- internal/session/budget_test.go | 4 +- internal/session/capability.go | 1 + internal/session/capability_test.go | 14 ++-- internal/session/collection_page_test.go | 4 +- internal/session/command_test.go | 16 ++-- internal/session/compaction_migration_test.go | 9 ++- internal/session/continuation_test.go | 3 +- internal/session/definition_test.go | 10 +-- internal/session/event_test.go | 13 ++-- internal/session/execution_engine_test.go | 16 ++-- internal/session/failure_test.go | 18 ++--- .../filesystem_access_migration_test.go | 10 ++- internal/session/filesystem_test.go | 4 +- internal/session/fork_test.go | 3 +- internal/session/mailbox_revision_test.go | 3 +- internal/session/mailbox_test.go | 3 +- internal/session/mcp_capability_test.go | 4 +- internal/session/migrations_test.go | 26 ++++--- internal/session/model_call_test.go | 4 +- internal/session/presentation_history_test.go | 5 +- internal/session/protocol_test.go | 14 ++-- internal/session/root_projection_test.go | 4 +- internal/session/runtime_storage_test.go | 2 +- internal/session/runtime_test.go | 36 ++++----- internal/session/session.go | 9 ++- internal/session/session_lifecycle_test.go | 5 +- internal/session/session_test.go | 42 ++++++----- internal/session/snapshot_view_test.go | 6 +- internal/session/span_test.go | 4 +- internal/session/state_test.go | 8 +- internal/session/swarm_test.go | 6 +- internal/session/timestamp_migration_test.go | 10 ++- internal/session/title_admission_test.go | 7 +- internal/session/title_test.go | 5 +- internal/session/tools_grant_test.go | 2 +- internal/session/transcript_page_test.go | 3 +- internal/session/transcript_test.go | 5 +- internal/session/turn_outcome_test.go | 8 +- internal/session/upcoming_schedule_test.go | 6 +- .../session/upcoming_schedule_time_test.go | 4 +- internal/tools/browser_desktop_test.go | 2 +- internal/tools/dispatcher_test.go | 6 +- internal/tools/jobs_test.go | 2 +- internal/tools/mcp_test.go | 2 +- internal/tui/client_integration_test.go | 2 +- 62 files changed, 331 insertions(+), 187 deletions(-) diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index 29d3487ee..184880d28 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -73,7 +73,8 @@ func runDaemon(ctx context.Context, args []string) error { if err != nil { return err } - store, err := session.Open(filepath.Join(paths.Home, "sessions.db")) + workspaces := capability.NewWorkspaces() + store, err := session.Open(filepath.Join(paths.Home, "sessions.db"), workspaces) if err != nil { return err } diff --git a/cmd/whip/daemon_client_test.go b/cmd/whip/daemon_client_test.go index 70413bd49..4984b2716 100644 --- a/cmd/whip/daemon_client_test.go +++ b/cmd/whip/daemon_client_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/session" @@ -20,7 +21,7 @@ func openRuntimeTestStore(t *testing.T, home string) *session.Store { if err := os.MkdirAll(filepath.Dir(runtimeDBPath(home)), 0o700); err != nil { t.Fatal(err) } - store, err := session.Open(runtimeDBPath(home)) + store, err := session.Open(runtimeDBPath(home), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/cmd/whip/desktop_runtime_sync_integration_test.go b/cmd/whip/desktop_runtime_sync_integration_test.go index 0aef7966d..f5ec6ff54 100644 --- a/cmd/whip/desktop_runtime_sync_integration_test.go +++ b/cmd/whip/desktop_runtime_sync_integration_test.go @@ -13,6 +13,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" @@ -74,7 +75,7 @@ func TestDesktopCompiledUpdate(t *testing.T) { } // Seed a scheduled session whose provider/model is no longer configured. // It must survive both cold startup and replacement without blocking readiness. - store, err := session.Open(filepath.Join(paths.Home, "sessions.db")) + store, err := session.Open(filepath.Join(paths.Home, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -168,7 +169,7 @@ func TestDesktopCompiledUpdate(t *testing.T) { } _ = client.Close() run(canonical, "daemon", "stop") - store, err = session.Open(filepath.Join(paths.Home, "sessions.db")) + store, err = session.Open(filepath.Join(paths.Home, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/cmd/whip/run_test.go b/cmd/whip/run_test.go index a510dd7c5..a2c91e859 100644 --- a/cmd/whip/run_test.go +++ b/cmd/whip/run_test.go @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" @@ -406,7 +407,9 @@ func TestRunQuietJSON(t *testing.T) { func configDir() (string, error) { return os.Getenv("WHIPCODE_HOME"), nil } -func sessionOpen(dir string) (*session.Store, error) { return session.Open(runtimeDBPath(dir)) } +func sessionOpen(dir string) (*session.Store, error) { + return session.Open(runtimeDBPath(dir), capability.NewWorkspaces()) +} // Bad flags, an unknown --format, and a missing prompt all fail before any // provider is contacted. @@ -604,7 +607,7 @@ func TestRunExecutionEngineSelectionAndResume(t *testing.T) { if err != nil { t.Fatal(err) } - store, err := session.Open(filepath.Join(os.Getenv("WHIPCODE_HOME"), "runtime-v2", "sessions.db")) + store, err := session.Open(filepath.Join(os.Getenv("WHIPCODE_HOME"), "runtime-v2", "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -630,7 +633,7 @@ func TestRunAgentSelectionAndResume(t *testing.T) { if _, err := runCapture(t, "", "--agent", "junior-developer", "--permission-mode", "automatic", "--max-tokens", "10000", "select agent"); err != nil { t.Fatal(err) } - store, err := session.Open(filepath.Join(os.Getenv("WHIPCODE_HOME"), "runtime-v2", "sessions.db")) + store, err := session.Open(filepath.Join(os.Getenv("WHIPCODE_HOME"), "runtime-v2", "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 4f2c3b30b..df381a062 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -651,7 +651,7 @@ prerequisite. The execution ledger below records subsequent repairs and results. All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. -The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 4a. +The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 6. The separate UI-readiness repair now precedes the compatibility gate so that PR #302 inherits that repair in its own required CI. The combined tree at the new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and @@ -676,7 +676,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Provider package extraction (plan PR 3b2) | `4b5c0e5790f698371abed1ed4c8bcf3dd9cd3885`, [PR #308](https://github.com/context-labs/whip/pull/308). | Eleven implementation files move to `internal/provider` with existing service/constructor names. The declaration proof preserves all 1,188 existing production declarations after type qualification; all 758 existing tests remain. Private tests move with the service; transport/runtime/default-pair/catalog-reload assertions remain in daemon. This code tree equals historical tested commit `f45cecb74dfe0c02826c044ace30112e53e0bccf`. Fresh publication-provenance compatibility passed against the new immediate parent. [Current CI](https://github.com/context-labs/whip/actions/runs/36685870687) and [security](https://github.com/context-labs/whip/actions/runs/36685870367) passed. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | | Startup factory extraction (plan PR 4a) | `b251786c8d868cba722f103d0a77ce72d07377f5`, [PR #309](https://github.com/context-labs/whip/pull/309). | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | | Host directory grouping (plan PR 4b) | `774623f12ef182856862209d186bc70150d17cf1`, [PR #310](https://github.com/context-labs/whip/pull/310). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | -| Process ownership (plan PR 5) | `057edb919da1a652fb284e2d54d4cf020a7867c6`, based on PR #310 (`774623f12ef182856862209d186bc70150d17cf1`). | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | +| Process ownership (plan PR 5) | `42285977df445ac79334ac96e465d44f057f0350`, [PR #311](https://github.com/context-labs/whip/pull/311), based on PR #310. | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | +| Workspace ownership (plan PR 6) | `codex/backend-reorg-06-workspace-ownership`, based on PR #311 (`42285977df445ac79334ac96e465d44f057f0350`). | A green, mutation-calibrated composition test precedes the ownership change. Host startup supplies one coordinator to storage; existing root/child/tool borrowers retain the same accessor and implementation. Validation and the deliberate remaining dependency are recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -963,3 +964,72 @@ an empty candidate diff and passes all calibrated transport/event, lifecycle, mutation-rejection, and both-engine fixed/immediate-base rollback checks. This recording update changes documentation only; hosted checks run on the published PR head. The PR remains unmerged for review. + + +### Workspace ownership (plan PR 6) + +Host startup now creates one `capability.Workspaces` immediately before +`session.Open(path, workspaces)`. Storage borrows the supplied coordinator and +rejects a nil argument explicitly. `Store.Workspaces()` remains the intentional +borrowed-reference boundary: authority validation and the existing runtime +borrowers already need the store, so they use its same coordinator. There are +no additional daemon/root pointer fields or constructor arguments, per-request +allocations, fallback construction, new interfaces, or cleanup methods. +`Workspaces.Open`, canonicalization and lock acquisition remain at their existing +call sites; the moved constructor only creates the empty coordination map. + +The baseline characterization was committed at +`1dcbacbb72c3ffda13938e21397e75e6e5bb7479` before production edits. It uses real +root, second-root, spawned-child, restored-child and tool-host services. Writes +through canonical and symlink aliases succeed before locking, wait until their +bounded contexts expire while the shared target is held, and succeed after +release. Target content stays unchanged while blocked, and unrelated-path writes +succeed concurrently with the held lock. Three race/shuffle runs passed on the +original implementation (17.193s). In a disposable snapshot, replacing only the +restored child's coordinator with a fresh instance caused the restored-child +lock assertion to fail, as required. After injection, the test also asserts +identity with the externally supplied coordinator and passed three race/shuffle +runs with the architecture guard (18.391s). + +The AST migration accounts for all 177 existing storage-open calls across 57 +files, including aliased imports and integration-tagged CLI/TUI/daemon fixtures. +Each storage lifetime receives one coordinator; existing fixture assertions and +cleanup remain unchanged. The source-conservation proof at +`/private/tmp/whip-workspace-conservation-proof.txt` preserves 578 existing +function declarations after normalizing only the added argument and the two +production constructor changes. The only other existing-test differences are +the new characterization's supplied-pointer checks and the architecture guard's +additional forbidden storage constructor. Every authority method is byte-identical; +entire delegation/admission, tools, dispatcher, workspace, runtime binding, +child cloning and skill-completion files are byte-identical. The frozen +content-only migration literal is untouched. + +Module build, vet and whipvet passed. CI's pinned golangci-lint 2.13.1 reported +zero issues, and daemon/TUI/CLI integration-tagged fixtures compiled. Full +race/shuffle suites passed: session (159.052s), capability (29.182s), tools +(18.324s), MCP (22.606s), daemon (274.455s), agent (10.175s), and CLI (80.987s). + +Fresh compatibility evidence is at +`/private/tmp/whip-workspace-compat-fresh/evidence.json`, using the fixed SDK +`271c0f8d2a35648d1b45056d57432590b783483c`, immediate parent +`42285977df445ac79334ac96e465d44f057f0350`, Go 1.27.0 darwin/arm64 and Node +24.14.1. The recorded candidate is the characterization commit plus its captured +staged source diff; later documentation updates do not change the tested source. +Fresh binaries passed Unix/WebSocket responses and ordered events, deliberate +response/order mutation rejection, cancellation/reconnect lifecycle and +fixed/immediate-base rollback for both engines with retained root/child state, +content, schema and trace/export. Candidate integration binary SHA-256: +`390f550a80c4017e6306710625cb1ad14b617a9637f6808bdfd46c6b2758a4b8`. + +Corrected inherited CI provenance is recorded at +`/private/tmp/whip-corrected-ci-audit.wDmPXD/provenance.json`. For immediate +parent PR #311, the downloaded Linux compatibility artifact identifies parent +`774623f12ef182856862209d186bc70150d17cf1` and the synthetic merge candidate for +published head `42285977df445ac79334ac96e465d44f057f0350`. Its +[CI run](https://github.com/context-labs/whip/actions/runs/36689454272) has passed +lint and Linux/macOS compatibility; its +[security run](https://github.com/context-labs/whip/actions/runs/36689453922) +passed. Its SDK job subsequently failed and is being classified before this +step is published; the full workflow is not claimed green. These corrected +artifacts supersede the earlier parent-provenance runs for this head; they do +not claim completion of other inherited workflows. diff --git a/internal/agent/authority_test.go b/internal/agent/authority_test.go index 8edbe9555..4fd7865af 100644 --- a/internal/agent/authority_test.go +++ b/internal/agent/authority_test.go @@ -17,7 +17,7 @@ func bindTestAgent(t *testing.T, ag *Agent, root string) { func bindTestServices(t *testing.T, services *tools.Services, root string) { t.Helper() - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/acceptance_test.go b/internal/daemon/acceptance_test.go index 8cae37509..95edf78e0 100644 --- a/internal/daemon/acceptance_test.go +++ b/internal/daemon/acceptance_test.go @@ -16,6 +16,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" @@ -137,7 +138,7 @@ func TestRuntimeAcceptanceDetachedRecoveryAndContextIsolation(t *testing.T) { t.Fatal(err) } - store, err := session.Open(database) + store, err := session.Open(database, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -349,7 +350,7 @@ func TestRuntimeAcceptanceDaemonHelper(t *testing.T) { t.Fatal(err) } defer func() { _ = owner.Close() }() - store, err := session.Open(filepath.Join(home, "sessions.db")) + store, err := session.Open(filepath.Join(home, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/architecture_test.go b/internal/daemon/architecture_test.go index 18a947f8a..58515abdb 100644 --- a/internal/daemon/architecture_test.go +++ b/internal/daemon/architecture_test.go @@ -133,8 +133,11 @@ func TestArchitectureKeepsProcessConstructionOutOfStorage(t *testing.T) { } ast.Inspect(file, func(node ast.Node) bool { if call, ok := node.(*ast.CallExpr); ok { - if constructor, ok := call.Fun.(*ast.SelectorExpr); ok && constructor.Sel.Name == "NewProcessManager" { - t.Errorf("storage constructs a live process manager: %s", path) + if constructor, ok := call.Fun.(*ast.SelectorExpr); ok { + switch constructor.Sel.Name { + case "NewProcessManager", "NewWorkspaces": + t.Errorf("storage constructs a host resource with %s: %s", constructor.Sel.Name, path) + } } } return true diff --git a/internal/daemon/autostart_test.go b/internal/daemon/autostart_test.go index 0ea39dc8a..fab08b789 100644 --- a/internal/daemon/autostart_test.go +++ b/internal/daemon/autostart_test.go @@ -187,7 +187,7 @@ func TestEnsureClientRejectsOldProtocolWithoutLaunching(t *testing.T) { } func startTestServer(path string, paths RuntimePaths, buildID string, generation int64, restart func()) (runningServer, error) { - store, err := session.Open(path) + store, err := session.Open(path, capability.NewWorkspaces()) if err != nil { return runningServer{}, err } diff --git a/internal/daemon/daemon_workspace_ownership_test.go b/internal/daemon/daemon_workspace_ownership_test.go index e929010c3..f555aa7b3 100644 --- a/internal/daemon/daemon_workspace_ownership_test.go +++ b/internal/daemon/daemon_workspace_ownership_test.go @@ -33,7 +33,11 @@ func TestWorkspaceCoordinatorIsSharedByRootsAndChildren(t *testing.T) { t.Fatal(err) } database := filepath.Join(t.TempDir(), "sessions.db") - store := openStore(t, database) + coordinator := capability.NewWorkspaces() + store, err := session.Open(database, coordinator) + if err != nil { + t.Fatal(err) + } ids := make([]string, 3) for i, cwd := range []string{directory, alias, alias} { kind := session.SessionKindAgent @@ -55,10 +59,16 @@ func TestWorkspaceCoordinatorIsSharedByRootsAndChildren(t *testing.T) { for _, incarnation := range []string{"new child", "restored child"} { t.Run(incarnation, func(t *testing.T) { if incarnation == "restored child" { - store = openStore(t, database) + coordinator = capability.NewWorkspaces() + store, err = session.Open(database, coordinator) + if err != nil { + t.Fatal(err) + } } t.Cleanup(func() { _ = store.Close() }) - coordinator := store.Workspaces() + if store.Workspaces() != coordinator { + t.Fatal("store did not borrow the supplied workspace coordinator") + } processes := newTestProcesses(t) limits := rlm.DefaultLimits() kernels := rlm.NewManager(limits.MaxWorkers) diff --git a/internal/daemon/input_test.go b/internal/daemon/input_test.go index c8f466d95..de45d6298 100644 --- a/internal/daemon/input_test.go +++ b/internal/daemon/input_test.go @@ -162,7 +162,7 @@ func TestPrepareAuthoredInputAttachesVisionImagesAndEnforcesChildCapability(t *t // workspace-scoped file grant is exercised rather than the detached shortcut. func storeBackedInputSession(t *testing.T, workspace string) *AgentSession { t.Helper() - store, err := sessionstore.Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := sessionstore.Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/restart_test.go b/internal/daemon/restart_test.go index f18b50bab..4d1fb2d54 100644 --- a/internal/daemon/restart_test.go +++ b/internal/daemon/restart_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -52,7 +53,7 @@ func TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution(t *test t.Fatal("detached in-flight call unexpectedly received a reply") } - store, err = session.Open(path) + store, err = session.Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/session_test.go b/internal/daemon/session_test.go index 1962feea7..7aa8a1a66 100644 --- a/internal/daemon/session_test.go +++ b/internal/daemon/session_test.go @@ -141,7 +141,7 @@ func newTestProcesses(t *testing.T) *capability.ProcessManager { func openStore(t *testing.T, path string) *session.Store { t.Helper() - store, err := session.Open(path) + store, err := session.Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/v2_crash_test.go b/internal/daemon/v2_crash_test.go index 33797738c..61cde37fd 100644 --- a/internal/daemon/v2_crash_test.go +++ b/internal/daemon/v2_crash_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/webgateway" @@ -99,7 +100,7 @@ func TestV2CrashAfterAcceptanceRecoversAcrossTransports(t *testing.T) { if err := json.Unmarshal(data, &accepted); err != nil { t.Fatal(err) } - store, err := session.Open(filepath.Join(home, "sessions.db")) + store, err := session.Open(filepath.Join(home, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/mcp/serve_test.go b/internal/mcp/serve_test.go index 61f1605a8..909a344ae 100644 --- a/internal/mcp/serve_test.go +++ b/internal/mcp/serve_test.go @@ -23,7 +23,7 @@ import ( // WHIP_TEST_SELFHOST-gated tests cover the real-subprocess path; this one // keeps Serve covered in plain CI. func TestServeInProcess(t *testing.T) { - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/agent_report_test.go b/internal/session/agent_report_test.go index 52e13403d..6613874b1 100644 --- a/internal/session/agent_report_test.go +++ b/internal/session/agent_report_test.go @@ -3,11 +3,13 @@ package session import ( "path/filepath" "testing" + + "github.com/context-labs/whip/internal/capability" ) func TestAgentReportModeSurvivesStoreReopenAndMetadataViews(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -43,7 +45,7 @@ func TestAgentReportModeSurvivesStoreReopenAndMetadataViews(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/browser_capability_test.go b/internal/session/browser_capability_test.go index 869853afe..36b339825 100644 --- a/internal/session/browser_capability_test.go +++ b/internal/session/browser_capability_test.go @@ -330,7 +330,7 @@ func TestBrowserAdmissionRejectsUnboundAndStaleGrant(t *testing.T) { func TestBrowserFreshChildAndReopen(t *testing.T) { path := filepath.Join(t.TempDir(), "session.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -347,7 +347,7 @@ func TestBrowserFreshChildAndReopen(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/budget_test.go b/internal/session/budget_test.go index 4f8c2c952..9b3a2ba7c 100644 --- a/internal/session/budget_test.go +++ b/internal/session/budget_test.go @@ -452,7 +452,7 @@ func TestCapBudgetWaitsForInheritedReservations(t *testing.T) { func TestRecoveryReleasesDescendantOperationAndAgentTurnReservations(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -493,7 +493,7 @@ func TestRecoveryReleasesDescendantOperationAndAgentTurnReservations(t *testing. if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/capability.go b/internal/session/capability.go index 1e943686f..c8457e25a 100644 --- a/internal/session/capability.go +++ b/internal/session/capability.go @@ -31,6 +31,7 @@ type storedCapabilityScopes struct { BrowserDelegationOnly bool `json:"browser_delegation_only,omitempty"` } +// Workspaces returns the coordinator borrowed from the store's caller. func (s *Store) Workspaces() *capability.Workspaces { return s.workspaces } // EnsureAuthority installs the root agent and its initial grants once. diff --git a/internal/session/capability_test.go b/internal/session/capability_test.go index 1ede6333b..7afbab7c1 100644 --- a/internal/session/capability_test.go +++ b/internal/session/capability_test.go @@ -17,7 +17,7 @@ import ( func TestCapabilityLedgerBindsAgentOperationBudgetAndScope(t *testing.T) { root := t.TempDir() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -132,7 +132,7 @@ func TestCapabilityLedgerBindsAgentOperationBudgetAndScope(t *testing.T) { func TestEnsureAuthorityIsIdempotent(t *testing.T) { root := t.TempDir() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -174,7 +174,7 @@ func TestEnsureAuthorityIsIdempotent(t *testing.T) { func TestCapabilityPermissionSurvivesDispatcherAndRevalidates(t *testing.T) { root := t.TempDir() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -239,7 +239,7 @@ func TestCapabilityPermissionSurvivesDispatcherAndRevalidates(t *testing.T) { func TestWorkspaceMutationRequiresDistinctRootWriter(t *testing.T) { root := t.TempDir() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -315,7 +315,7 @@ func TestWorkspaceMutationRequiresDistinctRootWriter(t *testing.T) { func TestPendingPermissionResumesAfterStoreReopen(t *testing.T) { root := t.TempDir() database := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(database) + st, err := Open(database, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -366,7 +366,7 @@ func TestPendingPermissionResumesAfterStoreReopen(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(database) + st, err = Open(database, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -920,7 +920,7 @@ func TestCapabilityValidationCorruptionAndRollbackPaths(t *testing.T) { func capabilityRoot(t *testing.T, workspace string) (*Store, string) { t.Helper() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/collection_page_test.go b/internal/session/collection_page_test.go index e1109b70d..189a43529 100644 --- a/internal/session/collection_page_test.go +++ b/internal/session/collection_page_test.go @@ -8,11 +8,13 @@ import ( "strings" "testing" "time" + + "github.com/context-labs/whip/internal/capability" ) func collectionStore(t *testing.T) (*Store, string) { t.Helper() - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/command_test.go b/internal/session/command_test.go index b0103cab2..37d157cbb 100644 --- a/internal/session/command_test.go +++ b/internal/session/command_test.go @@ -9,12 +9,14 @@ import ( "path/filepath" "sync" "testing" + + "github.com/context-labs/whip/internal/capability" ) func TestCreateSessionCommandPersistsPermissionWithOutcome(t *testing.T) { for _, mode := range []string{"", PermissionModePrompt, PermissionModeAutomatic, "invalid"} { t.Run("mode="+mode, func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -66,7 +68,7 @@ func TestCreateSessionCommandPersistsPermissionWithOutcome(t *testing.T) { } func TestCommandAdmissionIsIdempotentAndBoundToOneInboxSequence(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -130,7 +132,7 @@ func TestCommandAdmissionIsIdempotentAndBoundToOneInboxSequence(t *testing.T) { } func TestRootTurnCommitsProtocolCommandOutcome(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -189,7 +191,7 @@ func TestRootTurnCommitsProtocolCommandOutcome(t *testing.T) { } func TestDaemonCommandAdmissionHasIndependentSequence(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -209,7 +211,7 @@ func TestDaemonCommandAdmissionHasIndependentSequence(t *testing.T) { } func TestCommandAdmissionRejectsInvalidScopesAndMissingRecords(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -288,7 +290,7 @@ func TestCommandAdmissionRejectsInvalidScopesAndMissingRecords(t *testing.T) { } func TestCommandAPIsReturnClosedStoreErrors(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -314,7 +316,7 @@ func TestCommandAPIsReturnClosedStoreErrors(t *testing.T) { } func TestCommandExecutionStateIsDurableAndCannotResurrect(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/compaction_migration_test.go b/internal/session/compaction_migration_test.go index 13c48b5af..584e9533d 100644 --- a/internal/session/compaction_migration_test.go +++ b/internal/session/compaction_migration_test.go @@ -8,6 +8,7 @@ import ( "reflect" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -86,7 +87,7 @@ func TestCompactionPinSurvivesReopenAndFork(t *testing.T) { for _, pinned := range []bool{false, true} { t.Run(fmt.Sprintf("pinned=%t", pinned), func(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -126,7 +127,7 @@ func TestCompactionPinSurvivesReopenAndFork(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -145,7 +146,7 @@ func TestCompactionPinSurvivesReopenAndFork(t *testing.T) { func TestVersionTwentyCompactionsDoNotInferPins(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -167,7 +168,7 @@ UPDATE runtime_schema SET identity='whip-recursive-runtime-v20'; PRAGMA user_ver if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/continuation_test.go b/internal/session/continuation_test.go index 09a63f893..aaedf67b4 100644 --- a/internal/session/continuation_test.go +++ b/internal/session/continuation_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -16,7 +17,7 @@ func TestContinuationStaysDurableAndOutOfPublicHistory(t *testing.T) { name = "child" } t.Run(name, func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/definition_test.go b/internal/session/definition_test.go index f84d223bf..712768f24 100644 --- a/internal/session/definition_test.go +++ b/internal/session/definition_test.go @@ -45,7 +45,7 @@ func TestVersionFifteenUpgradeDefaultsDefinitionToCoding(t *testing.T) { t.Fatal(err) } for attempt := range 2 { - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatalf("open %d: %v", attempt, err) } @@ -90,7 +90,7 @@ func createDefinitionSession(t *testing.T, store *Store, definition string) (str func TestSessionDefinitionPersistsThroughForkAndReopen(t *testing.T) { path := filepath.Join(t.TempDir(), "definitions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -115,7 +115,7 @@ func TestSessionDefinitionPersistsThroughForkAndReopen(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -135,7 +135,7 @@ func TestSessionDefinitionPersistsThroughForkAndReopen(t *testing.T) { // Root grants come from the definition's capabilities at first bootstrap and // are never widened afterwards. func TestRootGrantsFollowDefinitionAtBootstrap(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "grants.db")) + store, err := Open(filepath.Join(t.TempDir(), "grants.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -191,7 +191,7 @@ func TestRootGrantsFollowDefinitionAtBootstrap(t *testing.T) { func TestRegisteredDefinitionsAreIdempotentAndPinned(t *testing.T) { path := filepath.Join(t.TempDir(), "registry.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/event_test.go b/internal/session/event_test.go index 0bf9cf8d5..3d0ed2e5d 100644 --- a/internal/session/event_test.go +++ b/internal/session/event_test.go @@ -10,11 +10,12 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) func TestEventReplayExpiresOldCursorsAndBoundsRetention(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -53,7 +54,7 @@ func TestEventReplayExpiresOldCursorsAndBoundsRetention(t *testing.T) { } func TestRootSnapshotAndActiveRootDiscovery(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -86,7 +87,7 @@ func TestRootSnapshotAndActiveRootDiscovery(t *testing.T) { } func TestRootSnapshotCarriesOnlyTheUncommittedPresentationTail(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -122,7 +123,7 @@ func TestRootSnapshotCarriesOnlyTheUncommittedPresentationTail(t *testing.T) { } func TestReplayAndSnapshotRejectInvalidCoordinates(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -145,7 +146,7 @@ func TestReplayAndSnapshotRejectInvalidCoordinates(t *testing.T) { } func TestReplayResolvesReferencedEventPayloadAndRejectsCorruptSnapshot(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -195,7 +196,7 @@ func TestReplayResolvesReferencedEventPayloadAndRejectsCorruptSnapshot(t *testin } func TestEventAPIsReturnClosedStoreErrors(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/execution_engine_test.go b/internal/session/execution_engine_test.go index 660c85a90..8fd56c642 100644 --- a/internal/session/execution_engine_test.go +++ b/internal/session/execution_engine_test.go @@ -8,6 +8,8 @@ import ( "path/filepath" "strings" "testing" + + "github.com/context-labs/whip/internal/capability" ) func createEngineSession(t *testing.T, store *Store, engine string) string { @@ -36,7 +38,7 @@ func TestSessionEngineTreeForkAndRestart(t *testing.T) { for _, engine := range []string{"starlark", "quickjs"} { t.Run(engine, func(t *testing.T) { path := filepath.Join(t.TempDir(), "engine.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -53,7 +55,7 @@ func TestSessionEngineTreeForkAndRestart(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -93,7 +95,7 @@ func TestSessionEngineTreeForkAndRestart(t *testing.T) { } func TestEngineCreationRetriesRetainSelection(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "engine.db")) + store, err := Open(filepath.Join(t.TempDir(), "engine.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -126,7 +128,7 @@ func testCheckpoint(t *testing.T, root, agent, engine string, image []byte) []by } func TestCheckpointIntegrityOwnershipAndPublication(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "engine.db")) + store, err := Open(filepath.Join(t.TempDir(), "engine.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -163,7 +165,7 @@ func TestCheckpointIntegrityOwnershipAndPublication(t *testing.T) { } func TestCheckpointRootQuotaAndDeletion(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "engine.db")) + store, err := Open(filepath.Join(t.TempDir(), "engine.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -196,7 +198,7 @@ func TestCheckpointRootQuotaAndDeletion(t *testing.T) { func TestExecutionEngineMigrationPreservesLegacyScratch(t *testing.T) { path := filepath.Join(t.TempDir(), "engine.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -210,7 +212,7 @@ func TestExecutionEngineMigrationPreservesLegacyScratch(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/failure_test.go b/internal/session/failure_test.go index 93a613a24..2c6a40bd9 100644 --- a/internal/session/failure_test.go +++ b/internal/session/failure_test.go @@ -16,7 +16,7 @@ import ( func TestRuntimeTransitionFailureRollsBackRowsAndDiagnosesBody(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -44,7 +44,7 @@ func TestRuntimeTransitionFailureRollsBackRowsAndDiagnosesBody(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -126,7 +126,7 @@ func TestActorPersistenceEventFailuresRollBack(t *testing.T) { func actorFailureFixture(t *testing.T) (*Store, string, string) { t.Helper() - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -154,7 +154,7 @@ func assertActorRows(t *testing.T, st *Store, rootID string, inbox, events int) func TestRecoveryFailureRollsBackEveryStatus(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -167,7 +167,7 @@ func TestRecoveryFailureRollsBackEveryStatus(t *testing.T) { exec(t, st, `CREATE TRIGGER reject_recovery BEFORE UPDATE ON operations BEGIN SELECT RAISE(ABORT,'recovery failure'); END`) st.Close() - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -194,7 +194,7 @@ func TestRecoveryFailureRollsBackEveryStatus(t *testing.T) { t.Fatal(err) } db.Close() - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -236,7 +236,7 @@ func TestOpenRejectsIncompatibleDatabase(t *testing.T) { if err := db.Close(); err != nil { t.Fatal(err) } - st, err := Open(p) + st, err := Open(p, capability.NewWorkspaces()) if err == nil { st.Close() t.Fatal("Open should reject a database whose schema collides with whip's") @@ -572,7 +572,7 @@ func TestUserHistorySkipsMalformedRows(t *testing.T) { // previous compaction's saved summary row — it covers history the new summary // does not reach. func TestApplyCompactionKeepsPriorSummary(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -616,7 +616,7 @@ func TestApplyCompactionKeepsPriorSummary(t *testing.T) { } func TestApplyCompactionRePinsOpeningMessageOfSplitTurn(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/filesystem_access_migration_test.go b/internal/session/filesystem_access_migration_test.go index 5c2378ed5..3af672152 100644 --- a/internal/session/filesystem_access_migration_test.go +++ b/internal/session/filesystem_access_migration_test.go @@ -6,6 +6,8 @@ import ( "fmt" "reflect" "testing" + + "github.com/context-labs/whip/internal/capability" ) func versionThirteenDatabase(t *testing.T) (string, *sql.DB) { @@ -56,7 +58,7 @@ func TestVersionThirteenUpgradePreservesAuthorityAndSessionState(t *testing.T) { } var firstCollection int64 for attempt := range 2 { - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -182,7 +184,7 @@ func TestVersionThirteenUpgradeOnlyTagsKnownBootstrapGrants(t *testing.T) { if err := db.Close(); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -226,7 +228,7 @@ func TestVersionThirteenUpgradeRollsBackAndRetries(t *testing.T) { BEGIN SELECT RAISE(ABORT,'upgrade failed'); END;`, scopes); err != nil { t.Fatal(err) } - if store, err := Open(path); err == nil { + if store, err := Open(path, capability.NewWorkspaces()); err == nil { _ = store.Close() t.Fatal("upgrade unexpectedly succeeded") } @@ -247,7 +249,7 @@ func TestVersionThirteenUpgradeRollsBackAndRetries(t *testing.T) { if _, err := db.ExecContext(t.Context(), `DROP TRIGGER reject_file_upgrade`); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/filesystem_test.go b/internal/session/filesystem_test.go index c15c20e22..126b50f16 100644 --- a/internal/session/filesystem_test.go +++ b/internal/session/filesystem_test.go @@ -20,7 +20,7 @@ func TestSessionFilesystemModeSurvivesRestartAndNavigation(t *testing.T) { } } db := filepath.Join(base, "sessions.db") - store, err := Open(db) + store, err := Open(db, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -59,7 +59,7 @@ func TestSessionFilesystemModeSurvivesRestartAndNavigation(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(db) + store, err = Open(db, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/fork_test.go b/internal/session/fork_test.go index 511d64204..86cff09c4 100644 --- a/internal/session/fork_test.go +++ b/internal/session/fork_test.go @@ -4,12 +4,13 @@ import ( "path/filepath" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) func seeded(t *testing.T) (*Store, string) { t.Helper() - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/mailbox_revision_test.go b/internal/session/mailbox_revision_test.go index c38b6a995..68c0a28a5 100644 --- a/internal/session/mailbox_revision_test.go +++ b/internal/session/mailbox_revision_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -332,7 +333,7 @@ func reopenMailboxStore(t *testing.T, store *Store) *Store { if err := store.Close(); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/mailbox_test.go b/internal/session/mailbox_test.go index 5f9a4c203..354c35ff9 100644 --- a/internal/session/mailbox_test.go +++ b/internal/session/mailbox_test.go @@ -9,12 +9,13 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) func newMailboxFixture(t *testing.T) (*Store, string, string) { t.Helper() - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/mcp_capability_test.go b/internal/session/mcp_capability_test.go index af70c2e87..9fc92f199 100644 --- a/internal/session/mcp_capability_test.go +++ b/internal/session/mcp_capability_test.go @@ -47,7 +47,7 @@ func delegateTestMCP(t *testing.T, store *Store, rootID, parentID, childID strin func TestMCPExactDelegationSurvivesReopen(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -68,7 +68,7 @@ func TestMCPExactDelegationSurvivesReopen(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/migrations_test.go b/internal/session/migrations_test.go index 1fe74a944..f6319d303 100644 --- a/internal/session/migrations_test.go +++ b/internal/session/migrations_test.go @@ -11,11 +11,13 @@ import ( "testing" _ "modernc.org/sqlite" + + "github.com/context-labs/whip/internal/capability" ) func TestFreshStoreUsesOnlyRecursiveSchema(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -59,7 +61,7 @@ func TestIncompatibleDevelopmentStoreIsRejectedWithoutMutation(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = Open(path) + _, err = Open(path, capability.NewWorkspaces()) if err == nil || !strings.Contains(err.Error(), path) || !strings.Contains(err.Error(), "archive or remove") { t.Fatalf("incompatible error=%v", err) } @@ -91,7 +93,7 @@ func TestVersionFiveStoreIsRejectedWithoutMutation(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := Open(path); err == nil { + if _, err := Open(path, capability.NewWorkspaces()); err == nil { t.Fatal("v5 database opened under current runtime") } after, err := os.ReadFile(path) @@ -131,7 +133,7 @@ func TestPhaseFourAndFiveStoresAreRejectedWithoutMutation(t *testing.T) { if err != nil { t.Fatal(err) } - if opened, err := Open(path); err == nil { + if opened, err := Open(path, capability.NewWorkspaces()); err == nil { opened.Close() t.Fatal("incompatible phase schema accepted") } @@ -147,7 +149,7 @@ func TestPhaseFourAndFiveStoresAreRejectedWithoutMutation(t *testing.T) { } func TestSessionKindsEnforceModelContract(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -204,7 +206,7 @@ func TestVersionTenUpgradePreservesStateAndRestarts(t *testing.T) { t.Fatal(err) } for attempt := range 2 { - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -272,7 +274,7 @@ func TestVersionTwelveUpgradePersistsPermissionMode(t *testing.T) { t.Fatal(err) } for attempt, want := range []string{PermissionModePrompt, PermissionModeAutomatic, PermissionModePrompt} { - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -317,7 +319,7 @@ func TestVersionTenUpgradeRollsBackAndCanRetry(t *testing.T) { if _, err := db.ExecContext(t.Context(), `DROP TRIGGER session_catalog_update`); err != nil { t.Fatal(err) } - if _, err := Open(path); err == nil { + if _, err := Open(path, capability.NewWorkspaces()); err == nil { t.Fatal("upgrade with missing v10 trigger succeeded") } var version, columns int @@ -338,7 +340,7 @@ func TestVersionTenUpgradeRollsBackAndCanRetry(t *testing.T) { BEGIN UPDATE runtime_schema SET catalog_revision=catalog_revision+1 WHERE id=1; END;`); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -351,7 +353,7 @@ func TestVersionTwelveUpgradeRollsBackAndRetries(t *testing.T) { BEGIN SELECT RAISE(ABORT,'upgrade failed'); END`); err != nil { t.Fatal(err) } - if store, err := Open(path); err == nil { + if store, err := Open(path, capability.NewWorkspaces()); err == nil { _ = store.Close() t.Fatal("upgrade unexpectedly succeeded") } @@ -368,7 +370,7 @@ func TestVersionTwelveUpgradeRollsBackAndRetries(t *testing.T) { if _, err := db.ExecContext(t.Context(), `DROP TRIGGER reject_mode_upgrade`); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -389,7 +391,7 @@ func TestVersionTwelveUpgradePreservesEventRetention(t *testing.T) { if err := db.Close(); err != nil { t.Fatal(err) } - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/model_call_test.go b/internal/session/model_call_test.go index a4ad50009..121c6b4d6 100644 --- a/internal/session/model_call_test.go +++ b/internal/session/model_call_test.go @@ -485,7 +485,7 @@ func TestModelSubtreeInterruptionIsScopedAndIdempotent(t *testing.T) { func TestModelRecoveryAfterReopenSettlesOnlyOnce(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -508,7 +508,7 @@ func TestModelRecoveryAfterReopenSettlesOnlyOnce(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/presentation_history_test.go b/internal/session/presentation_history_test.go index 541542a8b..eb484bd52 100644 --- a/internal/session/presentation_history_test.go +++ b/internal/session/presentation_history_test.go @@ -7,12 +7,13 @@ import ( "strings" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) func TestPresentationSurvivesBoundedPagesForkRewindCompactionAndReopen(t *testing.T) { file := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(file) + store, err := Open(file, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -72,7 +73,7 @@ func TestPresentationSurvivesBoundedPagesForkRewindCompactionAndReopen(t *testin if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(file) + store, err = Open(file, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/protocol_test.go b/internal/session/protocol_test.go index 4eb485ad0..cd1f3f860 100644 --- a/internal/session/protocol_test.go +++ b/internal/session/protocol_test.go @@ -5,11 +5,13 @@ import ( "errors" "path/filepath" "testing" + + "github.com/context-labs/whip/internal/capability" ) func TestDaemonGenerationIsDurable(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -23,7 +25,7 @@ func TestDaemonGenerationIsDurable(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -41,7 +43,7 @@ func TestDaemonGenerationIsDurable(t *testing.T) { func TestFormerApprovalTableDoesNotRequireDatabaseReset(t *testing.T) { path := filepath.Join(t.TempDir(), "runtime.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -59,7 +61,7 @@ func TestFormerApprovalTableDoesNotRequireDatabaseReset(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -72,7 +74,7 @@ func TestFormerApprovalTableDoesNotRequireDatabaseReset(t *testing.T) { func TestRuntimeIDAndCommandOperationSurviveReopen(t *testing.T) { path := filepath.Join(t.TempDir(), "runtime.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -90,7 +92,7 @@ func TestRuntimeIDAndCommandOperationSurviveReopen(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/root_projection_test.go b/internal/session/root_projection_test.go index 0f802be0c..947641ca2 100644 --- a/internal/session/root_projection_test.go +++ b/internal/session/root_projection_test.go @@ -3,6 +3,8 @@ package session import ( "path/filepath" "testing" + + "github.com/context-labs/whip/internal/capability" ) // The root agent's model, provider, effort and cwd are session facts that @@ -11,7 +13,7 @@ import ( // keep the selection they were admitted with. func TestRootAgentReadsDeriveSelectionFromSession(t *testing.T) { ctx := t.Context() - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/runtime_storage_test.go b/internal/session/runtime_storage_test.go index e42b8cfe0..c98ac8781 100644 --- a/internal/session/runtime_storage_test.go +++ b/internal/session/runtime_storage_test.go @@ -286,7 +286,7 @@ func TestArtifactDirectoryFailureCannotPublishUnrecoverableWork(t *testing.T) { for _, action := range []string{"store content", "enqueue input", "append event", "admit child", "send message", "finish command", "commit root outcome", "continue goal", "scheduled input"} { t.Run(action, func(t *testing.T) { directory := t.TempDir() - store, err := Open(filepath.Join(directory, "sessions.db")) + store, err := Open(filepath.Join(directory, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/runtime_test.go b/internal/session/runtime_test.go index f6197b346..d4479a259 100644 --- a/internal/session/runtime_test.go +++ b/internal/session/runtime_test.go @@ -19,7 +19,7 @@ import ( func TestRuntimeTransitionIsAtomicAndLargeValuesAreHandleBacked(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -106,7 +106,7 @@ func TestRuntimeTransitionIsAtomicAndLargeValuesAreHandleBacked(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -121,7 +121,7 @@ func TestRuntimeTransitionIsAtomicAndLargeValuesAreHandleBacked(t *testing.T) { } func TestRuntimeValueInlineBoundary(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -146,7 +146,7 @@ func TestRuntimeValueInlineBoundary(t *testing.T) { } func TestContentReferencesEnforceRootAgentAndSubtreeGrants(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -240,7 +240,7 @@ func TestContentReferencesEnforceRootAgentAndSubtreeGrants(t *testing.T) { func TestInboxSequencesPersistAndConsumedItemsDoNotReplay(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -322,7 +322,7 @@ func TestInboxSequencesPersistAndConsumedItemsDoNotReplay(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -393,7 +393,7 @@ func TestRootTurnLifecycleIdentifiesExactTurn(t *testing.T) { } func TestRootTurnCommitAtomicallyAppendsHistoryAndConsumesAcknowledgedInbox(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -461,7 +461,7 @@ func TestRootTurnCommitAtomicallyAppendsHistoryAndConsumesAcknowledgedInbox(t *t } func TestInternalTurnInboxDoesNotPersistACommandOutcome(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -493,7 +493,7 @@ func TestInternalTurnInboxDoesNotPersistACommandOutcome(t *testing.T) { } func TestRootTurnCommitPreservesRawHistoryAcrossCompaction(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -537,7 +537,7 @@ func TestRootTurnCommitPreservesRawHistoryAcrossCompaction(t *testing.T) { } func TestRootTurnCommitMapsCompactionsWithoutPersistedSystem(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -586,7 +586,7 @@ func TestRootTurnCommitMapsCompactionsWithoutPersistedSystem(t *testing.T) { } func TestRootTurnCommitRollsBackAsOneTransition(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -638,7 +638,7 @@ func TestRootTurnCommitRollsBackAsOneTransition(t *testing.T) { func TestScheduleFireClaimIsExactOnceAndGridAnchored(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -708,7 +708,7 @@ func TestScheduleFireClaimIsExactOnceAndGridAnchored(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -723,7 +723,7 @@ func TestScheduleFireClaimIsExactOnceAndGridAnchored(t *testing.T) { } func TestFailRootIsIsolatedAndPreservesTerminalRows(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -865,7 +865,7 @@ func TestFailRootIsIsolatedAndPreservesTerminalRows(t *testing.T) { func TestRecoveryInterruptsEveryNonterminalRuntimeRecord(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -887,7 +887,7 @@ func TestRecoveryInterruptsEveryNonterminalRuntimeRecord(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -939,7 +939,7 @@ func TestRecoveryInterruptsEveryNonterminalRuntimeRecord(t *testing.T) { func TestRecoveryReleasesOperationReservations(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -959,7 +959,7 @@ func TestRecoveryReleasesOperationReservations(t *testing.T) { if err := st.Close(); err != nil { t.Fatal(err) } - st, err = Open(path) + st, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/session.go b/internal/session/session.go index d33b31ff2..350c2c8cd 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -72,8 +72,11 @@ type Store struct { func (s *Store) AcquireDaemon() bool { return s.daemonOwned.CompareAndSwap(false, true) } func (s *Store) ReleaseDaemon() { s.daemonOwned.Store(false) } -// Open opens (creating if needed) the sessions database at path. -func Open(path string) (*Store, error) { +// Open opens (creating if needed) the sessions database at path and borrows workspaces. +func Open(path string, workspaces *capability.Workspaces) (*Store, error) { + if workspaces == nil { + return nil, errors.New("session store requires a workspace coordinator") + } db, err := sql.Open("sqlite", path) if err != nil { return nil, err @@ -107,7 +110,7 @@ func Open(path string) (*Store, error) { } store := &Store{ db: db, content: content, - workspaces: capability.NewWorkspaces(), + workspaces: workspaces, } failed = false return store, nil diff --git a/internal/session/session_lifecycle_test.go b/internal/session/session_lifecycle_test.go index f90be286e..cb80f2de9 100644 --- a/internal/session/session_lifecycle_test.go +++ b/internal/session/session_lifecycle_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -228,7 +229,7 @@ func lifecycleRows(t *testing.T, store *Store, rootID string) map[string]int { } func TestLifecycleForkExcludesRuntimeAndDeletePreservesOtherRoots(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -313,7 +314,7 @@ func TestLifecycleForkAndDeleteRollBack(t *testing.T) { } }) t.Run("delete complete tree", func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/session_test.go b/internal/session/session_test.go index e18c6f99a..fc42c8d38 100644 --- a/internal/session/session_test.go +++ b/internal/session/session_test.go @@ -7,11 +7,19 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) +func TestOpenRequiresWorkspaceCoordinator(t *testing.T) { + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), nil) + if store != nil || err == nil || err.Error() != "session store requires a workspace coordinator" { + t.Fatalf("Open without workspaces = %v, %v", store, err) + } +} + func TestDeleteSessionRemovesOwnedTree(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -74,7 +82,7 @@ func TestDeleteSessionRemovesOwnedTree(t *testing.T) { } func TestStoreRoundTrip(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -156,7 +164,7 @@ func TestStoreRoundTrip(t *testing.T) { } func TestRecentExcludesUntouchedBlankRoots(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -174,7 +182,7 @@ func TestRecentExcludesUntouchedBlankRoots(t *testing.T) { } func TestEffortRoundTrip(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -221,7 +229,7 @@ func TestEffortRoundTrip(t *testing.T) { func TestSessionsUseOneExecutionContract(t *testing.T) { path := filepath.Join(t.TempDir(), "s.db") - st, err := Open(path) + st, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -247,7 +255,7 @@ func TestSessionsUseOneExecutionContract(t *testing.T) { } func TestUserHistory(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -290,7 +298,7 @@ func TestUserHistory(t *testing.T) { // (steered background-task results, goal-continuation prompts) — only genuinely // typed submissions are recalled. func TestUserHistorySkipsInjected(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -317,10 +325,10 @@ func TestUserHistorySkipsInjected(t *testing.T) { } func TestStoreEdgeCases(t *testing.T) { - if _, err := Open("/nonexistent-dir/x.db"); err == nil { + if _, err := Open("/nonexistent-dir/x.db", capability.NewWorkspaces()); err == nil { t.Fatal("expected open error") } - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -346,7 +354,7 @@ func TestStoreEdgeCases(t *testing.T) { } func TestGoalPersistence(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -371,7 +379,7 @@ func TestGoalPersistence(t *testing.T) { // no result; Load must synthesize an error result so the resumed conversation // satisfies the API's tool_call/tool-result pairing contract. func TestLoadSynthesizesDanglingToolResults(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -428,7 +436,7 @@ func TestLoadSynthesizesDanglingToolResults(t *testing.T) { // Compaction is an event, not a rewrite: the raw log survives, Load derives // the compacted view, and a bad compaction can be deleted and retried. func TestCompactionEvent(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -520,7 +528,7 @@ func TestCompactionEvent(t *testing.T) { } func TestTodosAndUsagePersistence(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -564,7 +572,7 @@ func TestTodosAndUsagePersistence(t *testing.T) { } func TestClearMessages(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -590,7 +598,7 @@ func TestClearMessages(t *testing.T) { } func TestSnapshotRoundTrip(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -641,7 +649,7 @@ func TestSnapshotRoundTrip(t *testing.T) { } func TestRewindHistoryAtomicallyDropsDerivedTail(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -687,7 +695,7 @@ func TestRewindHistoryAtomicallyDropsDerivedTail(t *testing.T) { } func TestScheduleRoundTrip(t *testing.T) { - st, err := Open(filepath.Join(t.TempDir(), "s.db")) + st, err := Open(filepath.Join(t.TempDir(), "s.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/snapshot_view_test.go b/internal/session/snapshot_view_test.go index 0ed27bdec..6e0842cd1 100644 --- a/internal/session/snapshot_view_test.go +++ b/internal/session/snapshot_view_test.go @@ -4,10 +4,12 @@ import ( "encoding/json" "path/filepath" "testing" + + "github.com/context-labs/whip/internal/capability" ) func TestSnapshotRootViewBoundsHistoryAndKeepsCursor(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -39,7 +41,7 @@ func TestSnapshotRootViewBoundsHistoryAndKeepsCursor(t *testing.T) { } func TestSnapshotPresentationBudgetExcludesAccounting(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/span_test.go b/internal/session/span_test.go index 18b2f21b4..5e0e4fca8 100644 --- a/internal/session/span_test.go +++ b/internal/session/span_test.go @@ -456,7 +456,7 @@ func TestInternContentReusesReferencesAndPatchesSettledSpans(t *testing.T) { // must retain the conversation without inventing spans or requiring activity. func TestSpanMigrationPreservesHistoryWithoutBackfilling(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -477,7 +477,7 @@ func TestSpanMigrationPreservesHistoryWithoutBackfilling(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/state_test.go b/internal/session/state_test.go index bb47e8dba..4569b7767 100644 --- a/internal/session/state_test.go +++ b/internal/session/state_test.go @@ -10,6 +10,8 @@ import ( "strings" "sync" "testing" + + "github.com/context-labs/whip/internal/capability" ) func TestStatePrivateIsolationBlackboardVisibilityAndHandles(t *testing.T) { @@ -688,7 +690,7 @@ func snapshotStateFailure(t *testing.T, store *Store, rootID string) stateFailur } func TestAgentScratchSaveLoadAndDelete(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -724,7 +726,7 @@ func TestAgentScratchSaveLoadAndDelete(t *testing.T) { } func TestRecordScratchRestoreAppendsEvent(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -757,7 +759,7 @@ func TestRecordScratchRestoreAppendsEvent(t *testing.T) { } func TestLoadAgentScratchRejectsExistingEmptySnapshot(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/swarm_test.go b/internal/session/swarm_test.go index 703756c80..fe0c06024 100644 --- a/internal/session/swarm_test.go +++ b/internal/session/swarm_test.go @@ -11,7 +11,7 @@ import ( func newSwarmFixture(t *testing.T) (*Store, string, string) { t.Helper() - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -87,7 +87,7 @@ func TestAgentAdmissionPersistsPromptAtomically(t *testing.T) { func TestRecoveryKeepsQueuedAgentPromptButInterruptsRunningInput(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -113,7 +113,7 @@ func TestRecoveryKeepsQueuedAgentPromptButInterruptsRunningInput(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/timestamp_migration_test.go b/internal/session/timestamp_migration_test.go index 99a534808..b30fb3882 100644 --- a/internal/session/timestamp_migration_test.go +++ b/internal/session/timestamp_migration_test.go @@ -6,11 +6,13 @@ import ( "strings" "testing" "time" + + "github.com/context-labs/whip/internal/capability" ) func TestV20UpgradeNormalizesLegacyTimestampOrdering(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -71,7 +73,7 @@ PRAGMA user_version=20;`); err != nil { } for range 2 { // Reopening an upgraded store must preserve the same values. - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -114,7 +116,7 @@ PRAGMA user_version=20;`); err != nil { func TestTimestampNormalizationFailureRollsBackUpgrade(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -140,7 +142,7 @@ PRAGMA user_version=20;`); err != nil { if err := store.Close(); err != nil { t.Fatal(err) } - if reopened, err := Open(path); err == nil { + if reopened, err := Open(path, capability.NewWorkspaces()); err == nil { _ = reopened.Close() t.Fatal("incomplete schema unexpectedly upgraded") } else if !strings.Contains(err.Error(), "normalize legacy timestamps") { diff --git a/internal/session/title_admission_test.go b/internal/session/title_admission_test.go index c22b0e3ed..074705251 100644 --- a/internal/session/title_admission_test.go +++ b/internal/session/title_admission_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -78,7 +79,7 @@ func TestTitleInitializedAtAdmission(t *testing.T) { func TestTitleAttachmentOnlyWaitsAcrossTurnAndRestart(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -108,7 +109,7 @@ func TestTitleAttachmentOnlyWaitsAcrossTurnAndRestart(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -123,7 +124,7 @@ func TestTitleAttachmentOnlyWaitsAcrossTurnAndRestart(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/title_test.go b/internal/session/title_test.go index 056048719..c16e747d1 100644 --- a/internal/session/title_test.go +++ b/internal/session/title_test.go @@ -7,6 +7,7 @@ import ( "testing" "unicode/utf8" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -43,7 +44,7 @@ func TestProvisionalTitlePersistsAcrossWritePaths(t *testing.T) { want := strings.Repeat("界", provisionalTitleRunes-1) + "…" t.Run("Save", func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -62,7 +63,7 @@ func TestProvisionalTitlePersistsAcrossWritePaths(t *testing.T) { }) t.Run("CommitRootTurn", func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/tools_grant_test.go b/internal/session/tools_grant_test.go index 75b6c8041..c66f4e1c6 100644 --- a/internal/session/tools_grant_test.go +++ b/internal/session/tools_grant_test.go @@ -13,7 +13,7 @@ import ( // bootstrap, delegated by name to children, never widened, and added with no // operations to roots that predate it. func TestToolsGrantIssuesDelegatesAndNeverWidens(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "tools.db")) + store, err := Open(filepath.Join(t.TempDir(), "tools.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/transcript_page_test.go b/internal/session/transcript_page_test.go index dbe9e4402..25b982f67 100644 --- a/internal/session/transcript_page_test.go +++ b/internal/session/transcript_page_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -56,7 +57,7 @@ func TestTranscriptPagePreservesAssistantTimestamp(t *testing.T) { } func TestTranscriptPageBoundsRevisionAndRecent(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/transcript_test.go b/internal/session/transcript_test.go index 2216f2943..f7329ecbb 100644 --- a/internal/session/transcript_test.go +++ b/internal/session/transcript_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/llm" ) @@ -42,7 +43,7 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( for _, child := range []bool{false, true} { t.Run(fmt.Sprintf("child=%t", child), func(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -85,7 +86,7 @@ func TestTranscriptPreservesRootAndChildRawHistoryAcrossTwoCompactionsAndReopen( if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/turn_outcome_test.go b/internal/session/turn_outcome_test.go index 1cd7c0b89..2a298facf 100644 --- a/internal/session/turn_outcome_test.go +++ b/internal/session/turn_outcome_test.go @@ -6,6 +6,8 @@ import ( "strings" "testing" "unicode/utf8" + + "github.com/context-labs/whip/internal/capability" ) func queueOutcomeTurn(t *testing.T, store *Store, root, child, turn string) { @@ -120,7 +122,7 @@ func TestTurnOutcomeSubtreeInterruption(t *testing.T) { func TestLegacyTurnOutcomeMigration(t *testing.T) { path := filepath.Join(t.TempDir(), "sessions.db") - store, err := Open(path) + store, err := Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -184,7 +186,7 @@ func TestLegacyTurnOutcomeMigration(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -202,7 +204,7 @@ func TestLegacyTurnOutcomeMigration(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - store, err = Open(path) + store, err = Open(path, capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/upcoming_schedule_test.go b/internal/session/upcoming_schedule_test.go index f80059f32..5ac274d09 100644 --- a/internal/session/upcoming_schedule_test.go +++ b/internal/session/upcoming_schedule_test.go @@ -7,10 +7,12 @@ import ( "testing" "time" "unicode/utf8" + + "github.com/context-labs/whip/internal/capability" ) func TestUpcomingSchedulesIndependentOfHistoryAndClaims(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -93,7 +95,7 @@ func TestUpcomingSchedulesIndependentOfHistoryAndClaims(t *testing.T) { } func TestUpcomingSchedulesPromptAndAggregateBounds(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/session/upcoming_schedule_time_test.go b/internal/session/upcoming_schedule_time_test.go index 3772218f9..43b832ac2 100644 --- a/internal/session/upcoming_schedule_time_test.go +++ b/internal/session/upcoming_schedule_time_test.go @@ -5,6 +5,8 @@ import ( "path/filepath" "testing" "time" + + "github.com/context-labs/whip/internal/capability" ) func TestUpcomingSchedulesOffsetAndFractionalOccurrence(t *testing.T) { @@ -14,7 +16,7 @@ func TestUpcomingSchedulesOffsetAndFractionalOccurrence(t *testing.T) { {"whole second", "2026-09-20T17:00:00-06:00", "2026-09-20T23:00:00.000000000Z"}, } { t.Run(test.name, func(t *testing.T) { - store, err := Open(filepath.Join(t.TempDir(), "runtime.db")) + store, err := Open(filepath.Join(t.TempDir(), "runtime.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/tools/browser_desktop_test.go b/internal/tools/browser_desktop_test.go index fe9eec601..7df484360 100644 --- a/internal/tools/browser_desktop_test.go +++ b/internal/tools/browser_desktop_test.go @@ -116,7 +116,7 @@ func TestRevokeDesktopAttachmentsHandlesUnavailableProvider(t *testing.T) { func desktopTestServices(t *testing.T) (*Services, *countingLedger, *testDesktopProvider, capability.Authority) { t.Helper() - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/tools/dispatcher_test.go b/internal/tools/dispatcher_test.go index 7b9250fb6..b954e9759 100644 --- a/internal/tools/dispatcher_test.go +++ b/internal/tools/dispatcher_test.go @@ -41,7 +41,7 @@ func (l *countingLedger) lastAdmission() capability.Admission { func TestBoundToolsUseDispatcherWithoutChangingOutput(t *testing.T) { root := t.TempDir() - st, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -151,7 +151,7 @@ func TestBoundHostCallsHaveDistinctOperationIDs(t *testing.T) { if err := os.WriteFile(filepath.Join(workspace, "file.txt"), []byte("host call result\n"), 0o600); err != nil { t.Fatal(err) } - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } @@ -223,7 +223,7 @@ func TestBoundHostCallsHaveDistinctOperationIDs(t *testing.T) { func TestAuthorityCloneKeepsHostIntegrationsAndPermissionMode(t *testing.T) { root := t.TempDir() - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/tools/jobs_test.go b/internal/tools/jobs_test.go index 0eef30cf4..5646c6044 100644 --- a/internal/tools/jobs_test.go +++ b/internal/tools/jobs_test.go @@ -14,7 +14,7 @@ import ( func TestShellStartJobsAreOwnedCappedAndClosedWithServices(t *testing.T) { root := t.TempDir() - st, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + st, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/tools/mcp_test.go b/internal/tools/mcp_test.go index 7cb84fda5..a3e95dd8b 100644 --- a/internal/tools/mcp_test.go +++ b/internal/tools/mcp_test.go @@ -66,7 +66,7 @@ func (p *testMCPProvider) CallChecked(ctx context.Context, call capability.MCPCa func newMCPServices(t *testing.T) (*Services, *countingLedger, *testMCPProvider, capability.Authority) { t.Helper() - store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db")) + store, err := session.Open(filepath.Join(t.TempDir(), "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } diff --git a/internal/tui/client_integration_test.go b/internal/tui/client_integration_test.go index e7d7aa96c..bfcaf3b56 100644 --- a/internal/tui/client_integration_test.go +++ b/internal/tui/client_integration_test.go @@ -43,7 +43,7 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { if paths.Runtime != paths.Home { t.Cleanup(func() { _ = os.RemoveAll(paths.Runtime) }) } - store, err := session.Open(filepath.Join(paths.Home, "sessions.db")) + store, err := session.Open(filepath.Join(paths.Home, "sessions.db"), capability.NewWorkspaces()) if err != nil { t.Fatal(err) } From 067fe82cd90b99aed42efa80c24e3917ba96e820 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 01:52:45 -0700 Subject: [PATCH 43/67] test(webgateway): synchronize pipelined handshake rejection --- docs/backend-reorganization-plan.md | 62 ++++++++++++++++++++++++++- internal/webgateway/websocket_test.go | 8 ++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index df381a062..f6e2d63b2 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -1029,7 +1029,65 @@ published head `42285977df445ac79334ac96e465d44f057f0350`. Its [CI run](https://github.com/context-labs/whip/actions/runs/36689454272) has passed lint and Linux/macOS compatibility; its [security run](https://github.com/context-labs/whip/actions/runs/36689453922) -passed. Its SDK job subsequently failed and is being classified before this -step is published; the full workflow is not claimed green. These corrected +passed. At this pre-publication snapshot, its SDK job had subsequently failed +and classification was pending; the full workflow was not claimed green. The +following entry records publication and the later diagnosis. These corrected artifacts supersede the earlier parent-provenance runs for this head; they do not claim completion of other inherited workflows. + +### Separate gateway fixture synchronization repair + +Workspace ownership was published as [PR #312](https://github.com/context-labs/whip/pull/312) +at `26a6fec9b505fd6c00cd10d64c753c779509a2a4`, based on PR #311. Its +[CI](https://github.com/context-labs/whip/actions/runs/36692034286) and +[security](https://github.com/context-labs/whip/actions/runs/36692033890) workflows +started; full hosted acceptance remains pending. This separate test-only repair +starts from that exact head and changes no product or client implementation. + +PR #308's original [CI run, attempt 1](https://github.com/context-labs/whip/actions/runs/36689144507/attempts/1) +failed in `TestHandshakeFailClosedBeforePipelinedTraffic/different-runtime`: +the second browser write returned `broken pipe` before the assertions ran. +The gateway and its tests were unchanged from frozen development. The fake +backend replied immediately to initialization while the browser sent its two +frames separately, so correct handshake rejection could close the connection +before the second write. A diagnostic probe against unchanged PR #311 observed +the expected error response, upstream closure without forwarding, and browser +EOF before the second write in all three rejection modes. The Linux write error +was not reproduced locally on macOS, where that first post-close write was +accepted by the kernel. Diagnosis and external probes are preserved under +`/private/tmp/whip-corrected-ci-audit.wDmPXD/`. + +The fixture now holds the incompatible initialization response until both +browser writes have succeeded. Its per-subtest channel also observes test-context +cancellation so failed setup cannot strand the backend worker. Every existing +network-marker, protocol-error, and no-forwarded-request assertion remains +byte-identical, as does the rest of the test file after removing the eight added +lines. No sleeps, retries, ignored write errors, or product changes were added. +The preservation proof is `/private/tmp/whip-reorg-gateway-fixture-preservation.txt`. + +Local full gateway race/shuffle passed (1.499s), and the affected test passed +100 race/shuffle repetitions with the original CI shuffle seed (1.755s). Module +build, vet, whipvet, and full CI-pinned golangci-lint 2.13.1 passed with zero lint +issues. The separate pre-change diagnostic barrier probe +also passed 100 repetitions with an added scheduling delay; that delay exists +only in the external probe, not in this repair. + +One failed-job rerun of PR #308 was authorized after source attribution and +diagnosis. Its open head was verified unchanged at +`4b5c0e5790f698371abed1ed4c8bcf3dd9cd3885` immediately before the request; +attempt 2 is pending. The original failure remains recorded above. Corrected +PRs #306, #309, and #310 now have fully successful CI; all five corrected +#306/#308/#309/#310/#311 security workflows and both compatibility matrix jobs +passed, with the expected Linux parent/tree provenance verified. + +PR #311's original SDK job passed all 470 SDK and 1,380 app tests, then timed out +in the browser performance probe while recording committed markers. Its artifact +contained all 40 markers in the DOM but only 39 measurements, with no page errors. +A controlled snapshot/subscription handoff reproduced the same measurement gap +on both PR #311 and its unchanged immediate parent: the probe observed event +notifications but omitted a marker delivered in a snapshot. The source-level +diagnosis is `/private/tmp/whip-pr311-performance-diagnosis.md`. A separate +instrumentation repair is planned; it is not included here. One failed-job rerun +was authorized and requested on unchanged PR #311 head +`42285977df445ac79334ac96e465d44f057f0350`; attempt 2 remains pending. Neither +workflow is claimed fully green before its checks finish. diff --git a/internal/webgateway/websocket_test.go b/internal/webgateway/websocket_test.go index 1c4361488..e89120091 100644 --- a/internal/webgateway/websocket_test.go +++ b/internal/webgateway/websocket_test.go @@ -182,6 +182,7 @@ func TestHandshakeFailClosedBeforePipelinedTraffic(t *testing.T) { result.Generation++ } closed := make(chan error, 1) + pipelined := make(chan struct{}) socket := rawBackend(t, func(upstream protocoltransport.Transport) { first, err := upstream.ReadMessage() if err != nil { @@ -203,6 +204,12 @@ func TestHandshakeFailClosedBeforePipelinedTraffic(t *testing.T) { closed <- errors.New("missing network marker") return } + // Queue both browser frames before rejection can close the connection. + select { + case <-pipelined: + case <-t.Context().Done(): + return + } reply, _ := protocoltransport.MarshalFrame(protocoltransport.Message{ID: req.ID, Result: result}) if err := upstream.WriteMessage(reply); err != nil { closed <- err @@ -218,6 +225,7 @@ func TestHandshakeFailClosedBeforePipelinedTraffic(t *testing.T) { browser := dialBrowser(t, s.Endpoint()) sendFrame(t, browser, `{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocol_major":3}}`) sendFrame(t, browser, `{"jsonrpc":"2.0","id":2,"method":"daemon.ping"}`) + close(pipelined) reply := readMessage(t, browser) if reply.Error == nil { t.Fatal("incompatible daemon accepted") From 0081b66e5445b90d10e4d5ada7786335943a6edc Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:00:12 -0700 Subject: [PATCH 44/67] test(web): measure committed probes delivered in snapshots --- .github/workflows/ci.yml | 1 + apps/web/scripts/performance-probes.mjs | 82 +++++++++++++ apps/web/scripts/performance-probes.test.mjs | 118 +++++++++++++++++++ apps/web/scripts/performance.mjs | 73 +----------- docs/backend-reorganization-plan.md | 65 +++++++++- 5 files changed, 267 insertions(+), 72 deletions(-) create mode 100644 apps/web/scripts/performance-probes.mjs create mode 100644 apps/web/scripts/performance-probes.test.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4677b24b8..e9c123c82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,6 +223,7 @@ jobs: - run: WHIP_WEB_BROWSERS=chromium,firefox node apps/web/scripts/browser.mjs - run: node apps/web/scripts/model-picker.mjs - run: node apps/web/scripts/snapshot-refresh.mjs + - run: node --test apps/web/scripts/performance-probes.test.mjs - run: node apps/web/scripts/performance.mjs - run: npm run test:example - name: Shared verified renderer for desktop and release consumers diff --git a/apps/web/scripts/performance-probes.mjs b/apps/web/scripts/performance-probes.mjs new file mode 100644 index 000000000..c61f9d3de --- /dev/null +++ b/apps/web/scripts/performance-probes.mjs @@ -0,0 +1,82 @@ +// Self-contained: Playwright serializes this test instrumentation into the page. +export function installPerformanceProbes({ desktop, rootId }) { + window.__performanceEventLatency = []; + window.__performanceCommitDOM = []; + window.__performanceProbeOverflow = false; + window.__performanceIPCFrames = 0; + window.__performanceContentHandles = []; + const pending = []; + const seenCommits = new Set(); + const enqueue = (event, received) => { + const committed = event?.payload?.text?.includes('commit-probe-'); + if (event?.kind !== 'stream.text' || + !(committed || event.payload?.text?.includes('delta-'))) return; + if (committed && seenCommits.has(event.seq)) return; + if (pending.length >= 512 || (committed && seenCommits.size >= 128)) { + window.__performanceProbeOverflow = true; + return; + } + if (committed) seenCommits.add(event.seq); + pending.push({ + sequence: event.seq, + text: event.payload.text.replaceAll("**", ""), + start: received, + }); + }; + const receive = data => { + try { + const message = JSON.parse(data); + const handle = message.result?.content ?? (message.result?.reference_id ? message.result : undefined); + if (handle?.digest && !window.__performanceContentHandles.some(item => item.reference_id === handle.reference_id)) { + if (window.__performanceContentHandles.length >= 16) window.__performanceProbeOverflow = true; + else window.__performanceContentHandles.push({ reference_id: handle.reference_id, digest: handle.digest, size: handle.size }); + } + const received = performance.now(); + const event = message.params?.event; + if (event?.root_id === rootId) enqueue(event, received); + // A refresh can deliver a committed probe in the snapshot instead of + // a notification. Its own event sequence identifies the same commit. + // Keep ordinary delta latency samples notification-only. + if (message.result?.root_id === rootId) { + for (const item of message.result.presentation ?? []) { + if (item.payload?.text?.includes('commit-probe-')) enqueue(item, received); + } + } + } catch {} + }; + if (desktop) { + if (!window.whipDesktop) throw new Error('Desktop performance probe requires the real preload bridge'); + const stop = window.whipDesktop.onEvent(event => { + if (event.kind === 'frame') { window.__performanceIPCFrames++; receive(event.frame); } + }); + window.addEventListener('pagehide', stop, { once: true }); + } else { + const NativeWebSocket = window.WebSocket; + window.WebSocket = class extends NativeWebSocket { + constructor(...args) { super(...args); this.addEventListener('message', message => receive(message.data)); } + }; + } + new MutationObserver(() => { + const live = [...document.querySelectorAll('[data-message-id^=\"live:\"]')] + .map((element) => element.textContent) + .join('\n'); + for (let index = pending.length - 1; index >= 0; index--) { + if (!live.includes(pending[index].text)) continue; + const stamp = performance.now(); + if (pending[index].text.includes('commit-probe-')) { + if (window.__performanceCommitDOM.length >= 128) + window.__performanceProbeOverflow = true; + else + window.__performanceCommitDOM.push({ + sequence: pending[index].sequence, + marker: pending[index].text, + browser_ms: stamp, + received_ms: pending[index].start, + }); + } else if (window.__performanceEventLatency.length < 512) { + window.__performanceEventLatency.push(stamp - pending[index].start); + } else window.__performanceProbeOverflow = true; + pending.splice(index, 1); + } + }).observe(document, { subtree: true, childList: true, characterData: true }); +} diff --git a/apps/web/scripts/performance-probes.test.mjs b/apps/web/scripts/performance-probes.test.mjs new file mode 100644 index 000000000..a44cb0145 --- /dev/null +++ b/apps/web/scripts/performance-probes.test.mjs @@ -0,0 +1,118 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import vm from 'node:vm'; +import { installPerformanceProbes } from './performance-probes.mjs'; + +function fixture(desktop = false) { + let now = 0, mounted = '', mutate, desktopEvent; + class Socket { + addEventListener(_name, callback) { this.receive = callback; } + } + const window = { + WebSocket: Socket, + addEventListener() {}, + whipDesktop: { onEvent(callback) { desktopEvent = callback; return () => {}; } }, + }; + // Exercise the same self-contained serialization used by page.addInitScript. + const install = vm.runInNewContext(`(${installPerformanceProbes.toString()})`, { + window, + performance: { now: () => now }, + document: { querySelectorAll: () => [{ textContent: mounted }] }, + MutationObserver: class { constructor(callback) { mutate = callback; } observe() {} }, + }); + install({ desktop, rootId: 'root' }); + const socket = desktop ? undefined : new window.WebSocket(); + return { + receive(message, at) { + now = at; + const data = JSON.stringify(message); + if (desktop) desktopEvent({ kind: 'frame', frame: data }); + else socket.receive({ data }); + }, + paint(text, at) { mounted = text; now = at; mutate(); }, + commits: () => JSON.parse(JSON.stringify(window.__performanceCommitDOM)), + deltas: () => Array.from(window.__performanceEventLatency), + overflow: () => window.__performanceProbeOverflow, + }; +} + +const item = (seq = '910', text = ' commit-probe-001', kind = 'stream.text') => ({ seq, kind, payload: { text } }); +const snapshot = (events, root = 'root') => ({ result: { root_id: root, cursor: '9223372036854775807', presentation: events } }); +const notification = (event, root = 'root') => ({ params: { event: { ...event, root_id: root } } }); + +test('snapshot delivery measures each event sequence and its actual receipt and DOM times', async t => { + for (const desktop of [false, true]) { + await t.test(desktop ? 'desktop frames' : 'WebSocket messages', () => { + const f = fixture(desktop); + f.receive(snapshot([item()]), 10); + f.paint('different live row', 20); + assert.deepEqual(f.commits(), []); + f.paint('live commit-probe-001', 30); + assert.deepEqual(f.commits(), [{ sequence: '910', marker: ' commit-probe-001', received_ms: 10, browser_ms: 30 }]); + assert.deepEqual(f.deltas(), []); + }); + } + await t.test('40 mixed-route markers keep exact sequence identities distinct from the snapshot cursor', () => { + const f = fixture(); + const expected = []; + let live = 'live'; + for (let i = 1; i <= 40; i++) { + const sequence = String(9007199254740993n + BigInt(i)); + const marker = ' commit-probe-' + String(i).padStart(3, '0'); + const event = item(sequence, marker); + f.receive(i % 2 ? snapshot([event]) : notification(event), i * 10); + f.receive(snapshot([event]), i * 10 + 1); + live += marker; + f.paint(live, i * 10 + 5); + expected.push({ sequence, marker, received_ms: i * 10, browser_ms: i * 10 + 5 }); + } + assert.deepEqual(f.commits(), expected); + assert.equal(new Set(f.commits().map(value => value.sequence)).size, 40); + assert.equal(f.overflow(), false); + }); +}); + +test('duplicate commit deliveries retain the first receipt before and after DOM observation', async t => { + for (const first of ['notification', 'snapshot']) { + await t.test(`${first} first`, () => { + const f = fixture(); + const messages = [notification(item()), snapshot([item()])]; + if (first === 'snapshot') messages.reverse(); + f.receive(messages[0], 10); + f.receive(messages[1], 20); + f.paint('live commit-probe-001', 30); + f.receive(messages[0], 40); + f.receive(messages[1], 50); + f.paint('live commit-probe-001 extended', 60); + assert.deepEqual(f.commits(), [{ sequence: '910', marker: ' commit-probe-001', received_ms: 10, browser_ms: 30 }]); + }); + } +}); + +test('unrelated roots and snapshot deltas do not enter the measured populations', () => { + const f = fixture(); + f.receive(snapshot([item()], 'other-root'), 1); + f.receive(notification(item(), 'other-root'), 2); + f.receive({ result: { root_id: 'root', presentation: [], agent_presentations: { child: [item()] } } }, 3); + f.receive(snapshot([item('911', ' commit-probe-002', 'stream.reasoning')]), 4); + f.receive(snapshot([item('912', ' **delta-000**')]), 5); + f.paint('live commit-probe-001 commit-probe-002 delta-000', 10); + assert.deepEqual(f.commits(), []); + assert.deepEqual(f.deltas(), []); + f.receive(notification(item('913', ' **delta-001**')), 20); + f.paint('live delta-001', 35); + assert.deepEqual(f.deltas(), [15]); +}); + +test('commit deduplication and pending receipts remain bounded and flag overflow', () => { + const commits = fixture(); + const events = Array.from({ length: 129 }, (_, i) => item(String(i + 1), ' commit-probe-' + String(i + 1).padStart(3, '0'))); + commits.receive(snapshot(events), 10); + assert.equal(commits.overflow(), true); + commits.paint(events.map(event => event.payload.text).join(''), 20); + assert.equal(commits.commits().length, 128); + + const pending = fixture(); + for (let i = 0; i < 513; i++) pending.receive(notification(item(String(i), ` **delta-${i}**`)), i); + assert.equal(pending.overflow(), true); +}); diff --git a/apps/web/scripts/performance.mjs b/apps/web/scripts/performance.mjs index 5d1269c97..e5ddcdc77 100644 --- a/apps/web/scripts/performance.mjs +++ b/apps/web/scripts/performance.mjs @@ -5,6 +5,7 @@ import { chromium } from '@playwright/test'; import { createWhipClient } from '../../../packages/sdk/dist/index.js'; import { createSessionView } from '../../../packages/sdk/dist/state.js'; import { checkComposerReading } from './composer-reading.mjs'; +import { installPerformanceProbes } from './performance-probes.mjs'; import { eventually, startFixture, @@ -90,77 +91,7 @@ const calibrateClock = () => } return samples; }); -await page.addInitScript(({ desktop, rootId }) => { - window.__performanceEventLatency = []; - window.__performanceCommitDOM = []; - window.__performanceProbeOverflow = false; - window.__performanceIPCFrames = 0; - window.__performanceContentHandles = []; - const pending = []; - const receive = data => { - try { - const message = JSON.parse(data); - const handle = message.result?.content ?? (message.result?.reference_id ? message.result : undefined); - if (handle?.digest && !window.__performanceContentHandles.some(item => item.reference_id === handle.reference_id)) { - if (window.__performanceContentHandles.length >= 16) window.__performanceProbeOverflow = true; - else window.__performanceContentHandles.push({ reference_id: handle.reference_id, digest: handle.digest, size: handle.size }); - } - const event = message.params?.event; - if ( - event?.kind !== 'stream.text' || event.root_id !== rootId || - !( - event.payload?.text?.includes('delta-') || - event.payload?.text?.includes('commit-probe-') - ) - ) - return; - if (pending.length >= 512) { - window.__performanceProbeOverflow = true; - return; - } - pending.push({ - sequence: event.seq, - text: event.payload.text.replaceAll("**", ""), - start: performance.now(), - }); - } catch {} - }; - if (desktop) { - if (!window.whipDesktop) throw new Error('Desktop performance probe requires the real preload bridge'); - const stop = window.whipDesktop.onEvent(event => { - if (event.kind === 'frame') { window.__performanceIPCFrames++; receive(event.frame); } - }); - window.addEventListener('pagehide', stop, { once: true }); - } else { - const NativeWebSocket = window.WebSocket; - window.WebSocket = class extends NativeWebSocket { - constructor(...args) { super(...args); this.addEventListener('message', message => receive(message.data)); } - }; - } - new MutationObserver(() => { - const live = [...document.querySelectorAll('[data-message-id^=\"live:\"]')] - .map((element) => element.textContent) - .join('\n'); - for (let index = pending.length - 1; index >= 0; index--) { - if (!live.includes(pending[index].text)) continue; - const stamp = performance.now(); - if (pending[index].text.includes('commit-probe-')) { - if (window.__performanceCommitDOM.length >= 128) - window.__performanceProbeOverflow = true; - else - window.__performanceCommitDOM.push({ - sequence: pending[index].sequence, - marker: pending[index].text, - browser_ms: stamp, - received_ms: pending[index].start, - }); - } else if (window.__performanceEventLatency.length < 512) { - window.__performanceEventLatency.push(stamp - pending[index].start); - } else window.__performanceProbeOverflow = true; - pending.splice(index, 1); - } - }).observe(document, { subtree: true, childList: true, characterData: true }); -}, { desktop, rootId: fixture.info.root_id }); +await page.addInitScript(installPerformanceProbes, { desktop, rootId: fixture.info.root_id }); const rootRoute = `/h/${fixture.info.runtime_id}/s/${fixture.info.root_id}`; const requests = []; page.on('pageerror', (error) => errors.push(error.message)); diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index f6e2d63b2..662a1616e 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -651,7 +651,7 @@ prerequisite. The execution ledger below records subsequent repairs and results. All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. -The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 6. +The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 312 → 313 → performance-probe repair. The separate UI-readiness repair now precedes the compatibility gate so that PR #302 inherits that repair in its own required CI. The combined tree at the new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and @@ -678,6 +678,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Host directory grouping (plan PR 4b) | `774623f12ef182856862209d186bc70150d17cf1`, [PR #310](https://github.com/context-labs/whip/pull/310). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | | Process ownership (plan PR 5) | `42285977df445ac79334ac96e465d44f057f0350`, [PR #311](https://github.com/context-labs/whip/pull/311), based on PR #310. | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | | Workspace ownership (plan PR 6) | `codex/backend-reorg-06-workspace-ownership`, based on PR #311 (`42285977df445ac79334ac96e465d44f057f0350`). | A green, mutation-calibrated composition test precedes the ownership change. Host startup supplies one coordinator to storage; existing root/child/tool borrowers retain the same accessor and implementation. Validation and the deliberate remaining dependency are recorded below. | +| Gateway fixture synchronization | `067fe82cd90b99aed42efa80c24e3917ba96e820`, [PR #313](https://github.com/context-labs/whip/pull/313), following workspace ownership. | Eight test-only lines synchronize the two pipelined browser writes before backend rejection. Existing assertions remain exact; the detailed baseline diagnosis and checks are below. | +| Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1091,3 +1093,64 @@ instrumentation repair is planned; it is not included here. One failed-job rerun was authorized and requested on unchanged PR #311 head `42285977df445ac79334ac96e465d44f057f0350`; attempt 2 remains pending. Neither workflow is claimed fully green before its checks finish. + + +### Separate browser performance instrumentation repair + +The original PR #311 SDK failure remains recorded at [run +36689454272](https://github.com/context-labs/whip/actions/runs/36689454272), job +109802928468. The unchanged 30-second wait required 40 commit measurements; +its artifact recorded 39 unique observations, missing only `commit-probe-001`, +while all 40 markers appeared in the page. No browser errors were reported. +The controlled handoff reproduced this exact signature on PR #311 and its +immediate parent `774623f12ef182856862209d186bc70150d17cf1`: the marker arrived +in a snapshot while the SDK replaced its subscription. The prior probe only +observed event notifications. This is a preexisting measurement gap, not a +change to process ownership or SDK delivery. The original CI artifact lacks +raw frames, so the controlled trace establishes the matching causal mechanism +rather than claiming to recover that run's exact transport trace. + +The repair is based on gateway prerequisite PR #313, +`067fe82cd90b99aed42efa80c24e3917ba96e820`. The existing self-contained browser +initializer moves into `apps/web/scripts/performance-probes.mjs`; the performance +script passes that function directly to Playwright. Root-matching snapshot +presentation entries retain their actual decimal-string event sequences, not +the snapshot cursor. Bounded commit deduplication keeps the first WebSocket or +desktop-frame receipt across either route, and the existing MutationObserver +still records mounted live-row observation. Ordinary delta latency samples +remain notification-only. No product, SDK, protocol, dependency, timeout, +40-marker assertion, clock check, or existing capacity limit changes. + +The focused Node test imports the same installer and exercises its serialized +function with controlled receipt, DOM, and clock inputs. The exact original +initializer fails the snapshot and deduplication regressions; the repaired +installer passes all nine cases, including subtests. Coverage includes both +host bridges, 40 mixed-route markers with sequences beyond JavaScript's safe +integer range, repeated receipts before and after DOM observation, unrelated +roots and child presentation, snapshot delta exclusion, and overflow. CI runs +this regression beside the existing full performance command; every previous +workflow step remains unchanged. + +On this parent, protocol/browser generation and production asset packaging, +JavaScript syntax checks, workflow lint, and all 36 workflow/publication policy +tests passed. The complete ordinary browser performance run passed all 40 +marker and keyboard checks with a 0.384ms clock-correlation error bound. The +controlled handoff also passed all checks with a 0.357ms bound: first marker +sequence `910` arrived once in a snapshot and zero times in event notifications, +yet its actual receipt and DOM observation were recorded. Both runs retain the +original timeout and all performance checks. These local runs used Node +24.14.1, Go 1.27.0 darwin/arm64, and pinned Playwright 1.63.0; hosted CI remains +separate evidence. + +Exact conservation evidence is +`/private/tmp/whip-performance-probes-conservation.json`: after excluding only +the initializer import/extraction, the main script is byte-identical; original +globals, transport bridge, and DOM observer are exact, and the workflow gains +only the focused test command. Browser artifacts are under +`/private/tmp/whip-performance-probes-validation/{ordinary,controlled}/`. +The original-installer negative control and focused/workflow logs are +`/private/tmp/whip-performance-probes-{original-negative,focused,workflow-tests}.log`. +The causal investigation is preserved in +`/private/tmp/whip-pr311-performance-diagnosis.md`. No additional hosted rerun +was requested by this repair; the previously authorized PR #311 failed-job +rerun is independent of these results. This PR remains unmerged for review. From 1ed6409596e002b4043c9bb06b0eef42a27608b0 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:03:56 -0700 Subject: [PATCH 45/67] test(daemon): characterize command presentation before extraction --- internal/daemon/command_outcome_test.go | 105 ++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 internal/daemon/command_outcome_test.go diff --git a/internal/daemon/command_outcome_test.go b/internal/daemon/command_outcome_test.go new file mode 100644 index 000000000..1a9a59010 --- /dev/null +++ b/internal/daemon/command_outcome_test.go @@ -0,0 +1,105 @@ +package daemon + +import "testing" + +func TestDecodeCommandPresentation(t *testing.T) { + t.Parallel() + for _, test := range []struct { + name, operation, body, status, output, failure string + }{ + {name: "submit", operation: "submit", body: `{"text":"answer"}`, output: "answer"}, + {name: "steer", operation: "steer", body: `{"text":"answer"}`, output: "answer"}, + {name: "submit parts", operation: "submit.parts", body: `{"text":"answer"}`, output: "answer"}, + {name: "steer parts", operation: "steer.parts", body: `{"text":"answer"}`, output: "answer"}, + {name: "shell", operation: "shell.run", body: `{"text":"answer"}`, output: "answer"}, + {name: "tool", operation: "tool.call", body: `{"text":"answer"}`, output: "answer"}, + {name: "create", operation: "session.create", body: `{"root_id":"root"}`, output: "root"}, + {name: "open", operation: "session.open", body: `{"root_id":"root"}`, output: "root"}, + {name: "fork", operation: "session.fork", body: `{"root_id":"root"}`, output: "root"}, + {name: "delete", operation: "session.delete", body: `{"root_id":"root"}`, output: "root"}, + {name: "inspect", operation: "workspace.inspect", body: `{"path":"/workspace"}`, output: "/workspace"}, + {name: "set workspace", operation: "workspace.set", body: `{"path":"/workspace"}`, output: "/workspace"}, + {name: "rename", operation: "session.rename", body: `{"title":"title"}`, output: "title"}, + {name: "set goal", operation: "goal.set", body: `{"goal":"goal"}`, output: "goal"}, + {name: "run goal", operation: "goal.run", body: `{"goal":"goal"}`, output: "goal"}, + {name: "derive goal", operation: "goal.from-context", body: `{"goal":"goal"}`, output: "goal"}, + {name: "set effort", operation: "session.effort", body: `{"effort":"high"}`, output: "high"}, + {name: "get effort", operation: "session.effort.get", body: `{"effort":"high"}`, output: "high"}, + {name: "set model", operation: "session.model", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "get model", operation: "session.model.get", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "reload model", operation: "session.reload", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "empty success", operation: "submit"}, + {name: "empty failure", operation: "submit", status: "failed"}, + {name: "failed", operation: "submit", body: `{"message":"failure"}`, status: "failed", failure: "failure"}, + {name: "cancelled", operation: "submit", body: `{"message":"failure"}`, status: "cancelled", failure: "failure"}, + {name: "interrupted unknown operation", operation: "unknown", body: `{"message":"failure"}`, status: "interrupted", failure: "failure"}, + {name: "empty failure object", operation: "submit", body: `{}`, status: "failed"}, + {name: "null failure", operation: "submit", body: `null`, status: "failed"}, + {name: "null failure message", operation: "submit", body: `{"message":null}`, status: "failed"}, + {name: "malformed failure", operation: "submit", body: `{`, status: "failed", failure: "invalid structured command failure"}, + {name: "numeric failure message", operation: "submit", body: `{"message":1}`, status: "failed", failure: "invalid structured command failure"}, + {name: "invalid failure code", operation: "submit", body: `{"message":"failure","code":"bad"}`, status: "failed", failure: "invalid structured command failure"}, + {name: "invalid failure data", operation: "submit", body: `{"message":"failure","data":false}`, status: "failed", failure: "invalid structured command failure"}, + {name: "failure field case", operation: "submit", body: `{"MESSAGE":"failure"}`, status: "failed", failure: "failure"}, + {name: "status is case sensitive", operation: "submit", body: `{"text":"answer"}`, status: "FAILED", output: "answer"}, + {name: "ignored field and retained whitespace", operation: "submit", body: `{"text":" answer ","ignored":true}`, output: " answer "}, + {name: "null result field", operation: "submit", body: `{"text":null}`}, + {name: "missing result field", operation: "submit", body: `{}`, failure: "invalid command result field"}, + {name: "null result object", operation: "submit", body: `null`, failure: "invalid command result field"}, + {name: "result field case", operation: "submit", body: `{"Text":"answer"}`, failure: "invalid command result field"}, + {name: "numeric result field", operation: "submit", body: `{"text":1}`, failure: "invalid command result field"}, + {name: "object result field", operation: "submit", body: `{"text":{}}`, failure: "invalid command result field"}, + {name: "array result field", operation: "submit", body: `{"text":[]}`, failure: "invalid command result field"}, + {name: "malformed result", operation: "submit", body: `{`, failure: "invalid command result"}, + {name: "trailing result", operation: "submit", body: `{"text":"a"} {}`, failure: "invalid command result"}, + {name: "scalar result", operation: "submit", body: `"answer"`, failure: "invalid command result"}, + {name: "array result", operation: "submit", body: `[]`, failure: "invalid command result"}, + {name: "duplicate result field", operation: "submit", body: `{"text":"first","text":"last"}`, output: "last"}, + {name: "empty model", operation: "session.model", body: `{}`, output: "@"}, + {name: "null model", operation: "session.model", body: `null`, output: "@"}, + {name: "model only", operation: "session.model", body: `{"model":"m"}`, output: "m @"}, + {name: "provider only", operation: "session.model", body: `{"provider":"p"}`, output: "@ p"}, + {name: "model whitespace", operation: "session.model", body: `{"model":" m ","provider":" p "}`, output: "m @ p"}, + {name: "model field case", operation: "session.model", body: `{"MODEL":"m","PROVIDER":"p"}`, output: "m @ p"}, + {name: "malformed model", operation: "session.model", body: `{`, failure: "invalid model result"}, + {name: "numeric model", operation: "session.model", body: `{"model":1}`, failure: "invalid model result"}, + {name: "numeric provider", operation: "session.model", body: `{"provider":1}`, failure: "invalid model result"}, + {name: "invalid ignored model field", operation: "session.model", body: `{"reload_pending":"yes"}`, failure: "invalid model result"}, + {name: "unknown plain text", operation: "unknown", body: "answer", output: "answer"}, + {name: "unknown malformed json", operation: "unknown", body: `{`, output: `{`}, + {name: "unknown whitespace", operation: "unknown", body: " \n\t ", output: " \n\t "}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + output, failure := decodeCommandPresentation(test.operation, []byte(test.body), test.status) + if output != test.output || failure != test.failure { + t.Fatalf("presentation = (%q, %q), want (%q, %q)", output, failure, test.output, test.failure) + } + }) + } + if output, failure := decodeCommandPresentation("submit", nil, "failed"); output != "" || failure != "" { + t.Fatalf("nil failure body = (%q, %q)", output, failure) + } +} + +func TestFillCommandPresentation(t *testing.T) { + t.Parallel() + for _, test := range []struct { + name string + result CommandResult + output, failure string + }{ + {name: "retains output with explicit failure", result: CommandResult{Operation: "submit", Result: []byte(`{"text":"answer"}`), Failure: &RPCError{Message: "failure"}}, output: "answer", failure: "failure"}, + {name: "empty explicit failure overrides decode error", result: CommandResult{Operation: "submit", Result: []byte(`{`), Failure: &RPCError{}}}, + {name: "nil explicit failure retains decode error", result: CommandResult{Operation: "submit", Result: []byte(`{`)}, failure: "invalid command result"}, + {name: "empty body clears stale presentation", result: CommandResult{Operation: "submit", Output: "stale", Error: "stale"}}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + fillCommandPresentation(&test.result) + if test.result.Output != test.output || test.result.Error != test.failure { + t.Fatalf("presentation = (%q, %q), want (%q, %q)", test.result.Output, test.result.Error, test.output, test.failure) + } + }) + } +} From 3127d8ef67c3d59cd70f55ad697102e275c2a6fc Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:13:39 -0700 Subject: [PATCH 46/67] refactor(backend): isolate shared native connection plumbing --- .github/workflows/ci.yml | 2 + Taskfile.yaml | 1 + apps/desktop/scripts/startup.mjs | 2 +- cmd/whip/daemon.go | 7 +- cmd/whip/daemon_client.go | 5 +- cmd/whip/daemon_client_test.go | 3 +- cmd/whip/daemon_force_test.go | 7 +- cmd/whip/daemon_manage.go | 34 ++++---- cmd/whip/daemon_manage_test.go | 11 +-- cmd/whip/daemon_test.go | 13 +-- cmd/whip/desktop_runtime_sync.go | 5 +- .../desktop_runtime_sync_integration_test.go | 3 +- cmd/whip/desktop_runtime_sync_test.go | 3 +- cmd/whip/gateway_process.go | 3 +- cmd/whip/gateway_process_test.go | 10 ++- cmd/whip/update.go | 4 +- cmd/whip/web.go | 5 +- cmd/whip/web_test.go | 9 +- docs/architecture.md | 4 +- docs/backend-reorganization-plan.md | 80 +++++++++++++++++ internal/commandpresentation/presentation.go | 55 ++++++++++++ .../commandpresentation/presentation_test.go | 85 +++++++++++++++++++ internal/daemon/acceptance_test.go | 7 +- internal/daemon/architecture_test.go | 21 +++++ internal/daemon/autostart.go | 8 +- internal/daemon/autostart_test.go | 69 ++------------- internal/daemon/client.go | 11 +-- internal/daemon/client_control.go | 7 +- internal/daemon/command_outcome.go | 52 +----------- internal/daemon/command_outcome_test.go | 80 ----------------- internal/daemon/control.go | 17 +--- internal/daemon/gateway_test.go | 3 +- internal/daemon/maintenance_unix.go | 7 +- internal/daemon/maintenance_unix_test.go | 23 ++--- internal/daemon/protocol.go | 10 +-- internal/daemon/protocol_edge_test.go | 3 +- internal/daemon/server.go | 12 +-- internal/daemon/session.go | 7 +- internal/daemon/socket_unix.go | 75 +--------------- internal/daemon/socket_unix_test.go | 64 +++----------- internal/daemon/subscription.go | 4 +- .../daemon/subscription_lifecycle_test.go | 3 +- internal/daemon/v2_acceptance_test.go | 3 +- internal/daemon/v2_crash_test.go | 3 +- internal/daemon/v2_sdk_test.go | 3 +- .../{daemon => daemonconn}/autostart_unix.go | 2 +- internal/daemonconn/autostart_unix_test.go | 66 ++++++++++++++ internal/daemonconn/protocol.go | 17 ++++ internal/daemonconn/socket_unix.go | 79 +++++++++++++++++ internal/daemonconn/socket_unix_test.go | 51 +++++++++++ internal/session/create.go | 18 ++++ internal/tui/client.go | 7 +- internal/tui/client_integration_test.go | 3 +- 53 files changed, 647 insertions(+), 439 deletions(-) create mode 100644 internal/commandpresentation/presentation.go create mode 100644 internal/commandpresentation/presentation_test.go rename internal/{daemon => daemonconn}/autostart_unix.go (99%) create mode 100644 internal/daemonconn/autostart_unix_test.go create mode 100644 internal/daemonconn/protocol.go create mode 100644 internal/daemonconn/socket_unix.go create mode 100644 internal/daemonconn/socket_unix_test.go create mode 100644 internal/session/create.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9c123c82..3fb4400a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -177,6 +177,8 @@ jobs: cache: true - name: Daemon lifecycle and socket ownership run: go test -race ./internal/daemon -run '^(TestRuntimeAcceptance.*|TestRuntimePathsAndOwnerLock|TestOwnerOnlySocketRefusesUnsafeState)$' + - name: Shared native connection and command presentation + run: go test -race ./internal/daemonconn ./internal/commandpresentation - name: Compact agent receipts and grant retrieval run: go test -race -tags=integration ./internal/daemon -run '^TestRecursiveAgent(ReceiptsWithLargeMCPGrants|GrantInspectionAccess)$' - name: RLM worker containment diff --git a/Taskfile.yaml b/Taskfile.yaml index a55895615..3815ffd7a 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -102,6 +102,7 @@ tasks: acceptance: desc: "Run the deterministic daemon, recursive-agent, client, and RLM release acceptance suite" cmds: + - go test -race ./internal/daemonconn ./internal/commandpresentation - go test -race -tags=integration ./internal/tui -run '^TestInteractiveSessionOverTrustedProtocol$' - go test -race -tags=integration ./internal/daemon -run '^TestRecursiveAgent(ReceiptsWithLargeMCPGrants|GrantInspectionAccess)$' - go test -race ./internal/daemon ./internal/session ./internal/protocol -run '^(TestV2|TestV3|TestTrustedClient|TestRuntimeRegistry|TestCommandAcceptance|TestClientAcceptance|TestDeleteAcceptance|TestQuestionSnapshot|TestRootCollection|TestSessionCatalog|TestIncompatible|TestVersionFive|TestVersionSix|TestBounded|TestTranscriptPage)' diff --git a/apps/desktop/scripts/startup.mjs b/apps/desktop/scripts/startup.mjs index 6d64e81fa..4be9245a8 100644 --- a/apps/desktop/scripts/startup.mjs +++ b/apps/desktop/scripts/startup.mjs @@ -44,7 +44,7 @@ async function eventually(check, label, timeout = 35_000) { throw new Error(`Startup fixture timed out: ${label}`); } async function fixtureStatus(executable, env) { - // internal/daemon/socket_unix.go uses this path below 100 bytes, otherwise a + // internal/daemonconn/socket_unix.go uses this path below 100 bytes, otherwise a // hashed temporary runtime. Keep our fixtures short and prove the exact path. const socket = path.join(env.WHIPCODE_HOME, 'runtime-v2/daemon.sock'); assert(Buffer.byteLength(socket) < 100, 'Use a shorter fixture home'); diff --git a/cmd/whip/daemon.go b/cmd/whip/daemon.go index 184880d28..1d3c2f9bd 100644 --- a/cmd/whip/daemon.go +++ b/cmd/whip/daemon.go @@ -14,18 +14,19 @@ import ( "github.com/context-labs/whip/internal/buildinfo" "github.com/context-labs/whip/internal/capability" - providersvc "github.com/context-labs/whip/internal/provider" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/webgateway" ) var ( - restartDaemonBinary = daemon.RestartSelfDaemon + restartDaemonBinary = daemonconn.RestartSelfDaemon daemonKernelCommand []string ) @@ -52,7 +53,7 @@ func runDaemon(ctx context.Context, args []string) error { if err != nil { return err } - paths, err := daemon.Paths(dir) + paths, err := daemonconn.Paths(dir) if err != nil { return err } diff --git a/cmd/whip/daemon_client.go b/cmd/whip/daemon_client.go index 3085390fd..5c116fd14 100644 --- a/cmd/whip/daemon_client.go +++ b/cmd/whip/daemon_client.go @@ -10,6 +10,7 @@ import ( "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) var connectDaemon = func(ctx context.Context, clientKind, clientID string, cursors map[string]int64) (daemon.RootConnection, error) { @@ -17,7 +18,7 @@ var connectDaemon = func(ctx context.Context, clientKind, clientID string, curso if err != nil { return nil, err } - paths, err := daemon.Paths(dir) + paths, err := daemonconn.Paths(dir) if err != nil { return nil, err } @@ -28,7 +29,7 @@ var connectDaemon = func(ctx context.Context, clientKind, clientID string, curso ClientID: clientID, Capabilities: []string{"commands", "events", "snapshots", "execution_engines"}, Cursors: cursors, - }, func() error { return daemon.LaunchSelfDaemon(paths) }) + }, func() error { return daemonconn.LaunchSelfDaemon(paths) }) } func daemonConnector(clientKind, clientID string) daemon.RootConnector { diff --git a/cmd/whip/daemon_client_test.go b/cmd/whip/daemon_client_test.go index 4984b2716..b55002d93 100644 --- a/cmd/whip/daemon_client_test.go +++ b/cmd/whip/daemon_client_test.go @@ -11,6 +11,7 @@ import ( "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/session" ) @@ -43,7 +44,7 @@ func useTestDaemon(t *testing.T) { if err != nil { return nil, err } - paths, err := daemon.Paths(dir) + paths, err := daemonconn.Paths(dir) if err != nil { return nil, err } diff --git a/cmd/whip/daemon_force_test.go b/cmd/whip/daemon_force_test.go index 789b57202..494950605 100644 --- a/cmd/whip/daemon_force_test.go +++ b/cmd/whip/daemon_force_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) func TestManagedOwnerProcess(t *testing.T) { @@ -37,7 +38,7 @@ func TestManagedOwnerProcess(t *testing.T) { func TestForcedDaemonStopOnlySignalsItsRecordedOwner(t *testing.T) { for _, ignoreTERM := range []bool{false, true} { t.Run(map[bool]string{false: "graceful", true: "kill fallback"}[ignoreTERM], func(t *testing.T) { - paths, err := daemon.Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -72,7 +73,7 @@ func TestForcedDaemonStopOnlySignalsItsRecordedOwner(t *testing.T) { } func TestForcedDaemonStopRefusesAmbiguousOwnership(t *testing.T) { - paths, err := daemon.Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -110,7 +111,7 @@ func TestDaemonCommandsSurfaceUnavailableHomeAndLaunchErrors(t *testing.T) { previous := launchManagedDaemon t.Cleanup(func() { launchManagedDaemon = previous }) launchErr := errors.New("fixture launch refused") - launchManagedDaemon = func(daemon.RuntimePaths) error { return launchErr } + launchManagedDaemon = func(daemonconn.RuntimePaths) error { return launchErr } for _, command := range []string{"start", "restart"} { if err := daemonManageCLI([]string{command}); !errors.Is(err, launchErr) { t.Fatalf("%s lost launch error: %v", command, err) diff --git a/cmd/whip/daemon_manage.go b/cmd/whip/daemon_manage.go index b9b6870d6..529e0bbc3 100644 --- a/cmd/whip/daemon_manage.go +++ b/cmd/whip/daemon_manage.go @@ -14,9 +14,9 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" - "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -24,7 +24,7 @@ import ( const daemonManageTimeout = 10 * time.Second var ( - launchManagedDaemon = daemon.LaunchSelfDaemon + launchManagedDaemon = daemonconn.LaunchSelfDaemon findDaemonProcess = os.FindProcess tailDaemonLog = func(path string, lines int, follow bool) error { args := []string{"-n", strconv.Itoa(lines)} @@ -76,26 +76,26 @@ func daemonManageCLI(args []string) error { } } -func daemonRuntimePaths() (daemon.RuntimePaths, error) { +func daemonRuntimePaths() (daemonconn.RuntimePaths, error) { dir, err := config.Dir() if err != nil { - return daemon.RuntimePaths{}, err + return daemonconn.RuntimePaths{}, err } - return daemon.Paths(dir) + return daemonconn.Paths(dir) } -func daemonStatusPaths() (daemon.RuntimePaths, error) { +func daemonStatusPaths() (daemonconn.RuntimePaths, error) { home := os.Getenv(buildinfo.Env("HOME")) if home == "" { userHome, err := os.UserHomeDir() if err != nil { - return daemon.RuntimePaths{}, err + return daemonconn.RuntimePaths{}, err } home = buildinfo.Home(userHome) } - paths, err := daemon.ResolvePaths(home) + paths, err := daemonconn.ResolvePaths(home) if err != nil { - return daemon.RuntimePaths{}, err + return daemonconn.RuntimePaths{}, err } for _, dir := range []string{paths.Home, paths.Runtime} { info, err := os.Stat(dir) @@ -103,10 +103,10 @@ func daemonStatusPaths() (daemon.RuntimePaths, error) { continue } if err != nil { - return daemon.RuntimePaths{}, err + return daemonconn.RuntimePaths{}, err } if !info.IsDir() { - return daemon.RuntimePaths{}, fmt.Errorf("daemon runtime path is not a directory: %s", dir) + return daemonconn.RuntimePaths{}, fmt.Errorf("daemon runtime path is not a directory: %s", dir) } } return paths, nil @@ -252,7 +252,7 @@ func daemonLogsCLI(args []string) error { return tailDaemonLog(path, *lines, *follow) } -func probeDaemon(paths daemon.RuntimePaths, timeout time.Duration) (daemonStatus, *daemon.Client) { +func probeDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) (daemonStatus, *daemon.Client) { status := daemonStatus{ State: "stopped", ClientBuild: version, Socket: paths.Socket, Gateway: protocol.GatewayStatus{State: "stopped"}, GatewayLog: filepath.Join(paths.Home, "web.log"), @@ -305,14 +305,14 @@ func probeDaemon(paths daemon.RuntimePaths, timeout time.Duration) (daemonStatus return status, client } -func startManagedDaemon(paths daemon.RuntimePaths, timeout time.Duration) (daemonStatus, error) { +func startManagedDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) (daemonStatus, error) { // A ready socket means an owned daemon even if its optional gateway failed. // Repeated starts must never reconfigure it or spawn duplicate daemons. if status, client := probeDaemon(paths, min(time.Second, timeout)); client != nil { _ = client.Close() return status, nil } - if err := launchManagedDaemon(paths); err != nil && !errors.Is(err, daemon.ErrDaemonOwned) { + if err := launchManagedDaemon(paths); err != nil && !errors.Is(err, daemonconn.ErrDaemonOwned) { return daemonStatus{}, err } deadline := time.Now().Add(timeout) @@ -342,7 +342,7 @@ func startManagedDaemon(paths daemon.RuntimePaths, timeout time.Duration) (daemo return latest, fmt.Errorf("daemon did not become ready within %s; inspect %s", timeout, filepath.Join(paths.Home, "daemon.log")) } -func stopManagedDaemon(paths daemon.RuntimePaths, timeout time.Duration, force bool) (bool, error) { +func stopManagedDaemon(paths daemonconn.RuntimePaths, timeout time.Duration, force bool) (bool, error) { deadline := time.Now().Add(timeout) status, client := probeDaemon(paths, min(time.Second, timeout)) if client == nil { @@ -387,7 +387,7 @@ func stopManagedDaemon(paths daemon.RuntimePaths, timeout time.Duration, force b return true, forceStopManagedDaemon(paths, timeout) } -func waitForDaemonStop(paths daemon.RuntimePaths, timeout time.Duration) error { +func waitForDaemonStop(paths daemonconn.RuntimePaths, timeout time.Duration) error { deadline := time.Now().Add(timeout) for { _, owned, err := daemon.ActiveOwnerPID(paths.Lock) @@ -401,7 +401,7 @@ func waitForDaemonStop(paths daemon.RuntimePaths, timeout time.Duration) error { } } -func forceStopManagedDaemon(paths daemon.RuntimePaths, timeout time.Duration) error { +func forceStopManagedDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) error { pid, owned, err := daemon.ActiveOwnerPID(paths.Lock) if err != nil { return fmt.Errorf("identify daemon owner: %w", err) diff --git a/cmd/whip/daemon_manage_test.go b/cmd/whip/daemon_manage_test.go index 39967b550..d0e1eb359 100644 --- a/cmd/whip/daemon_manage_test.go +++ b/cmd/whip/daemon_manage_test.go @@ -14,6 +14,7 @@ import ( "github.com/context-labs/whip/internal/buildinfo" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) func TestDaemonStatusDoesNotInitializeHome(t *testing.T) { @@ -32,7 +33,7 @@ func TestDaemonStatusDoesNotInitializeHome(t *testing.T) { home = filepath.Join(userHome, "custom-home") t.Setenv(buildinfo.Env("HOME"), home) } - paths, err := daemon.ResolvePaths(home) + paths, err := daemonconn.ResolvePaths(home) if err != nil { t.Fatal(err) } @@ -54,7 +55,7 @@ func TestDaemonStatusDoesNotInitializeHome(t *testing.T) { func TestDaemonStatusPreservesExistingRuntime(t *testing.T) { home := t.TempDir() t.Setenv(buildinfo.Env("HOME"), home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -86,7 +87,7 @@ func TestDaemonStatusPreservesExistingRuntime(t *testing.T) { } func TestDaemonStatusIdentifiesOnlyUnownedStaleSocket(t *testing.T) { - paths, err := daemon.Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -123,7 +124,7 @@ func TestDaemonStatusIdentifiesOnlyUnownedStaleSocket(t *testing.T) { func TestDaemonManagementLifecycle(t *testing.T) { home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -131,7 +132,7 @@ func TestDaemonManagementLifecycle(t *testing.T) { previousLaunch := launchManagedDaemon previousTail := tailDaemonLog var daemonRuns []chan error - launchManagedDaemon = func(daemon.RuntimePaths) error { + launchManagedDaemon = func(daemonconn.RuntimePaths) error { done := make(chan error, 1) daemonRuns = append(daemonRuns, done) go func() { done <- runDaemon(t.Context(), nil) }() diff --git a/cmd/whip/daemon_test.go b/cmd/whip/daemon_test.go index ddd508c2b..411148d97 100644 --- a/cmd/whip/daemon_test.go +++ b/cmd/whip/daemon_test.go @@ -22,6 +22,7 @@ import ( "github.com/context-labs/whip/internal/agentdef" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" @@ -61,7 +62,7 @@ func TestRunDaemonPublishesProtocolAndStopsCleanly(t *testing.T) { defer cancel() done := make(chan error, 1) go func() { done <- runDaemon(ctx, nil) }() - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -219,7 +220,7 @@ func TestRunDaemonAlwaysUsesRLMRuntime(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) done := make(chan error, 1) go func() { done <- runDaemon(ctx, nil) }() - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -492,7 +493,7 @@ func TestConfigureRuntimeCompactionClampsLegacyThresholds(t *testing.T) { func TestRunDaemonRejectsOwnedAndInvalidHomes(t *testing.T) { home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -500,7 +501,7 @@ func TestRunDaemonRejectsOwnedAndInvalidHomes(t *testing.T) { if err != nil { t.Fatal(err) } - if err := runDaemon(context.Background(), nil); !errors.Is(err, daemon.ErrDaemonOwned) { + if err := runDaemon(context.Background(), nil); !errors.Is(err, daemonconn.ErrDaemonOwned) { t.Fatalf("second daemon owner = %v", err) } _ = owner.Close() @@ -515,7 +516,7 @@ func TestRunDaemonRejectsOwnedAndInvalidHomes(t *testing.T) { func TestRunDaemonCompletesCheckpointRestartHandoff(t *testing.T) { home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -561,7 +562,7 @@ func TestRunDaemonCompletesCheckpointRestartHandoff(t *testing.T) { func TestRunDaemonCompletesCheckpointStop(t *testing.T) { home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } diff --git a/cmd/whip/desktop_runtime_sync.go b/cmd/whip/desktop_runtime_sync.go index e17463a92..f8ab5d719 100644 --- a/cmd/whip/desktop_runtime_sync.go +++ b/cmd/whip/desktop_runtime_sync.go @@ -18,6 +18,7 @@ import ( "github.com/context-labs/whip/internal/buildinfo" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) const desktopBinaryLimit = 512 << 20 @@ -132,7 +133,7 @@ func syncDesktopRuntime(ctx context.Context, source string, options desktopSyncO if err := ctx.Err(); err != nil { return result, err } - if err := daemon.LaunchInstalledDaemon(paths, options.executable, maintenance); err != nil { + if err := daemonconn.LaunchInstalledDaemon(paths, options.executable, maintenance); err != nil { return result, fmt.Errorf("start updated backend: %w", err) } for { @@ -215,7 +216,7 @@ func stageDesktopRuntime(ctx context.Context, source, parent, expected string) ( return name, nil } -func stopDesktopOwner(ctx context.Context, paths daemon.RuntimePaths) error { +func stopDesktopOwner(ctx context.Context, paths daemonconn.RuntimePaths) error { pid, owned, err := daemon.ActiveOwnerPID(paths.Lock) if err != nil || !owned { return err diff --git a/cmd/whip/desktop_runtime_sync_integration_test.go b/cmd/whip/desktop_runtime_sync_integration_test.go index f5ec6ff54..806cc70d1 100644 --- a/cmd/whip/desktop_runtime_sync_integration_test.go +++ b/cmd/whip/desktop_runtime_sync_integration_test.go @@ -15,6 +15,7 @@ import ( "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -69,7 +70,7 @@ func TestDesktopCompiledUpdate(t *testing.T) { } _ = os.RemoveAll(directory) }) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } diff --git a/cmd/whip/desktop_runtime_sync_test.go b/cmd/whip/desktop_runtime_sync_test.go index 081345234..613805eb6 100644 --- a/cmd/whip/desktop_runtime_sync_test.go +++ b/cmd/whip/desktop_runtime_sync_test.go @@ -15,6 +15,7 @@ import ( "github.com/context-labs/whip/internal/buildinfo" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) func syncFixture(t *testing.T) (string, desktopSyncOptions) { @@ -93,7 +94,7 @@ func TestDesktopSyncCoordinatesRealOwnerAndReadiness(t *testing.T) { } options.digest, _ = desktopBinaryDigest(source) options.interrupt = true - if err := daemon.LaunchInstalledDaemon(paths, options.executable, nil); err != nil { + if err := daemonconn.LaunchInstalledDaemon(paths, options.executable, nil); err != nil { t.Fatal(err) } t.Cleanup(func() { diff --git a/cmd/whip/gateway_process.go b/cmd/whip/gateway_process.go index b6c940669..698531b5c 100644 --- a/cmd/whip/gateway_process.go +++ b/cmd/whip/gateway_process.go @@ -18,6 +18,7 @@ import ( "github.com/context-labs/whip/internal/buildinfo" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webgateway" ) @@ -182,7 +183,7 @@ func (child *managedGateway) stop(grace time.Duration) { } } -func manageGateway(ctx context.Context, paths daemon.RuntimePaths, generation int64, setStatus func(protocol.GatewayStatus)) { +func manageGateway(ctx context.Context, paths daemonconn.RuntimePaths, generation int64, setStatus func(protocol.GatewayStatus)) { fail := func(err error) { if ctx.Err() != nil { setStatus(protocol.GatewayStatus{State: "stopped"}) diff --git a/cmd/whip/gateway_process_test.go b/cmd/whip/gateway_process_test.go index d925e97a4..79af0a0bc 100644 --- a/cmd/whip/gateway_process_test.go +++ b/cmd/whip/gateway_process_test.go @@ -22,7 +22,7 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" ) // The test executable dispatches the same private runner without requiring a @@ -305,14 +305,18 @@ func TestManagedGatewayStatusFailureAndRepeatedStart(t *testing.T) { t.Cleanup(func() { launchManagedDaemon = previousLaunch }) home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(t.Context()) done := make(chan error, 1) launches := 0 - launchManagedDaemon = func(daemon.RuntimePaths) error { launches++; go func() { done <- runDaemon(ctx, nil) }(); return nil } + launchManagedDaemon = func(daemonconn.RuntimePaths) error { + launches++ + go func() { done <- runDaemon(ctx, nil) }() + return nil + } defer func() { cancel() select { diff --git a/cmd/whip/update.go b/cmd/whip/update.go index a394eacec..e37c5b70f 100644 --- a/cmd/whip/update.go +++ b/cmd/whip/update.go @@ -11,9 +11,9 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" - "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/update" ) @@ -82,7 +82,7 @@ var restartDaemonAfterUpdate = func() error { if err != nil { return err } - paths, err := daemon.Paths(dir) + paths, err := daemonconn.Paths(dir) if err != nil { return err } diff --git a/cmd/whip/web.go b/cmd/whip/web.go index 77b0de838..0d8d5aed6 100644 --- a/cmd/whip/web.go +++ b/cmd/whip/web.go @@ -18,6 +18,7 @@ import ( "time" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webassets" "github.com/context-labs/whip/internal/webgateway" @@ -74,7 +75,7 @@ func runWeb(ctx context.Context, args []string) error { // Both public foreground and private managed modes use this runner. The Open // factory always narrows socket privileges and fails closed on old daemons. -func runGateway(ctx context.Context, paths daemon.RuntimePaths, expected *gatewayReady, ready func(gatewayReady) error) error { +func runGateway(ctx context.Context, paths daemonconn.RuntimePaths, expected *gatewayReady, ready func(gatewayReady) error) error { options := gatewayEnvironment() options.SocketPath = paths.Socket options.Open = func(ctx context.Context) (webgateway.Client, error) { @@ -127,7 +128,7 @@ func runGateway(ctx context.Context, paths daemon.RuntimePaths, expected *gatewa } } -func dialGatewayClient(ctx context.Context, paths daemon.RuntimePaths) (*daemon.Client, error) { +func dialGatewayClient(ctx context.Context, paths daemonconn.RuntimePaths) (*daemon.Client, error) { client, err := daemon.DialClient(ctx, paths, daemon.InitializeParams{ ProtocolMajor: daemon.ProtocolMajor, BuildID: version, ClientID: daemonClientID("web-gateway"), ClientKind: "automation", diff --git a/cmd/whip/web_test.go b/cmd/whip/web_test.go index eba5ff586..f08b7da5d 100644 --- a/cmd/whip/web_test.go +++ b/cmd/whip/web_test.go @@ -18,6 +18,7 @@ import ( "time" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/protocoltransport" ) @@ -67,7 +68,7 @@ func TestWebCLIExplicitURLNeverStartsRuntime(t *testing.T) { } return true } - launchManagedDaemon = func(daemon.RuntimePaths) error { + launchManagedDaemon = func(daemonconn.RuntimePaths) error { t.Fatal("web command must never launch or replace runtime") return nil } @@ -121,7 +122,7 @@ func TestWebStoppedDaemonIsNotStarted(t *testing.T) { func TestGatewayDialRequiresCapabilityAcknowledgement(t *testing.T) { for _, ack := range []bool{false, true} { t.Run(fmt.Sprintf("ack=%t", ack), func(t *testing.T) { - paths, err := daemon.Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -196,11 +197,11 @@ func TestGatewayDialRequiresCapabilityAcknowledgement(t *testing.T) { } } -func startWebTestDaemon(t *testing.T) daemon.RuntimePaths { +func startWebTestDaemon(t *testing.T) daemonconn.RuntimePaths { t.Helper() home := t.TempDir() t.Setenv("WHIPCODE_HOME", home) - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } diff --git a/docs/architecture.md b/docs/architecture.md index 2d39c09a7..b14cf2ece 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -141,8 +141,10 @@ budgets, and private transcript. | --- | --- | | `internal/protocol`, `packages/protocol` | typed operation/event contract, generated Draft-07 schemas, TypeScript and Ajv | | `internal/daemon` | shared handlers, Unix/WebSocket/HTTP adapters, root actors, recursive runtime, lifecycle | +| `internal/daemonconn` | shared runtime paths, validated local dialing, native launch primitives, initialization limits and event envelope; daemon retains ownership locks and lifecycle policy | +| `internal/commandpresentation` | shared formatting of stored command results for existing native text presenters | | `internal/provider` | host provider configuration, discovery, catalogs and account login lifetimes; borrows existing config/auth storage and exposes operations to daemon without importing it | -| `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery | +| `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery and the native session creation value | | `internal/agentdef` | agent definitions and their registry: instructions and discovery toggles, selected modules and capabilities, model and compaction defaults, named children, and the capability-to-operation mapping; `Coding()` and `JuniorDeveloper()` are the first-party definitions | | `internal/rlm` | kernel process, Starlark modules, runtime guide fragments, focused-context composer | | `internal/capability` | identities, grants, path policy, operation admission | diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 662a1616e..e2382af77 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -1154,3 +1154,83 @@ The causal investigation is preserved in `/private/tmp/whip-pr311-performance-diagnosis.md`. No additional hosted rerun was requested by this repair; the previously authorized PR #311 failed-job rerun is independent of these results. This PR remains unmerged for review. + +### PR 7 — Shared native connection plumbing + +This step starts from browser instrumentation prerequisite [PR #314](https://github.com/context-labs/whip/pull/314), +`0081b66e5445b90d10e4d5ada7786335943a6edc`. Its +[CI](https://github.com/context-labs/whip/actions/runs/36693408346) and +[security](https://github.com/context-labs/whip/actions/runs/36693408075) runs +started; this local evidence does not claim that those full hosted runs passed. +All active PRs remain unmerged. + +`internal/daemonconn` now owns the existing runtime path calculation, validated +local dialing, native launch/exec primitives, shared limits and event envelope. +Daemon still owns runtime/startup/maintenance locks, inherited descriptor +validation, readiness retry policy and lifecycle decisions. The single mutable +`ErrDaemonOwned` binding is used directly at all eight call sites. Launch and +restart still share one executable lookup seam; CLI callbacks keep their +existing owners. `Paths` retains its filesystem effects, `ResolvePaths` remains +read-only, and the dial/initialize deadline asymmetry is preserved. + +The exact native `CreateSession` value moves to session with a daemon type alias, +including `DefinitionRevision`, field order and JSON tags. The existing command +presentation decoder moves once to `internal/commandpresentation`; native client +implementation, outcome encoding and `fillCommandPresentation` remain in daemon +for now. These shared homes allow the following client package move without +making clients depend on server implementation or adding translation/forwarding +functions. Existing exported daemon chunk/buffer constants are immutable aliases +of the shared constants. Protocol, framing, provider policy, SQL and schema +sources are unchanged. + +Characterization commit `1ed6409596e002b4043c9bb06b0eef42a27608b0` preceded every +production edit. Its named table covers all 21 recognized operations, exact +failure/status/JSON quirks, unknown-operation raw bytes, empty model `@`, and +explicit failure precedence. Those tests plus existing launch/path/maintenance +checks passed three race repetitions on unchanged production (8.452s). A +throwaway Go overlay removing `@` failed the exact empty-model assertion; the +mutation never touched repository source. After extraction the same three-run +checks passed: daemonconn 1.481s, commandpresentation 1.795s, daemon 8.314s. + +Four existing primitive tests move with their implementation. Mixed ownership +and socket integration tests remain in daemon, including the fixed 100-byte +boundary assertion. Existing Taskfile/CI selectors and assertions remain; one +focused daemonconn/commandpresentation command is added to acceptance and the +existing Linux/macOS runtime matrix. The frozen SDK bridge remains in daemon +with its original integration/Unix tags. A narrow architecture check prohibits +the shared helper packages from importing daemon. The current architecture map +and desktop fixture's source-location comment follow the new ownership. + +The type-aware extraction records 156 resolved identifier edits and verifies +original bytes before replacing them. The resulting proof covers 684 declarations +across 48 files: 459 function bodies, including 105 named tests, match the exact +expected reference/extraction changes. A separate comparison preserves all 29 +selected moved/retained declaration bodies, including owner locks, autostart +policy and encoders. Imports and comments are outside token comparisons. The +only descriptive correction changes the decoder's misleading inherited +plain-text prohibition to an accurate stored-outcome description; its raw-byte +fallback remains unchanged. Evidence is +`/private/tmp/whip-pr7-{transform-journal.json,caller-conservation.log,declaration-conservation.log}`. + +Local module build, vet, whipvet, integration-tag compilation and pinned +CI-equivalent golangci-lint 2.13.1 passed with zero lint findings. The complete +TUI race/shuffle suite passed in a real PTY (18.844s), and all 36 workflow policy +tests passed. Full affected-package race/shuffle passed: daemonconn 1.773s, +commandpresentation 1.419s, daemon 271.359s, session 156.806s, ACP 2.033s and +CLI 80.477s. Logs are `/private/tmp/whip-pr7-full-race.log`, +`/private/tmp/whip-pr7-tui.log`, and the matching build/vet/whipvet/lint/tagged +compile/workflow logs under `/private/tmp/whip-pr7-*`. + +Fresh fixed-SDK and immediate-parent compatibility passed, including immutable +sources and freshly generated artifacts, both transports' calibrated response/ +error/ordered-event comparisons, deliberate response/order mutation rejection, +lifecycle behavior and both-engine fixed-base/immediate-base → candidate → base +rollback with root/child state, content, schema and trace/export checks. +Evidence: `/private/tmp/whip-pr7-compat-fresh/evidence.json`, with Go 1.27.0 +(darwin/arm64), Node 24.14.1 and the original fixed SDK revision +`271c0f8d2a35648d1b45056d57432590b783483c`. The candidate binary SHA-256 is +`3ba071e27e6e0e082871d5c0e0a828549bf02889d0f98fa779f4449962b6bf19`. +This pre-commit local run records the characterization SHA plus its complete +staged extraction diff. Only the reviewed decoder comment and this ledger were +updated afterward; no executable behavior changed. Hosted checks will record +the final commit and actual PR parent separately. diff --git a/internal/commandpresentation/presentation.go b/internal/commandpresentation/presentation.go new file mode 100644 index 000000000..c1a8e7597 --- /dev/null +++ b/internal/commandpresentation/presentation.go @@ -0,0 +1,55 @@ +package commandpresentation + +import ( + "encoding/json" + "strings" + + "github.com/context-labs/whip/internal/protocol" +) + +// Decode formats stored command outcomes for existing text presenters. +func Decode(operation string, body []byte, status string) (string, string) { + if len(body) == 0 { + return "", "" + } + if status == "failed" || status == "cancelled" || status == "interrupted" { + var failure protocol.RPCError + if err := json.Unmarshal(body, &failure); err != nil { + return "", "invalid structured command failure" + } + return "", failure.Message + } + field := "" + switch operation { + case "submit", "steer", "submit.parts", "steer.parts", "shell.run", "tool.call": + field = "text" + case "session.create", "session.open", "session.fork", "session.delete": + field = "root_id" + case "workspace.inspect", "workspace.set": + field = "path" + case "session.rename": + field = "title" + case "goal.set", "goal.run", "goal.from-context": + field = "goal" + case "session.effort", "session.effort.get": + field = "effort" + case "session.model", "session.model.get", "session.reload": + var result protocol.ModelResult + if err := json.Unmarshal(body, &result); err != nil { + return "", "invalid model result" + } + return strings.TrimSpace(result.Model + " @ " + result.Provider), "" + } + if field != "" { + var values map[string]json.RawMessage + if json.Unmarshal(body, &values) != nil { + return "", "invalid command result" + } + var text string + if json.Unmarshal(values[field], &text) != nil { + return "", "invalid command result field" + } + return text, "" + } + return string(body), "" +} diff --git a/internal/commandpresentation/presentation_test.go b/internal/commandpresentation/presentation_test.go new file mode 100644 index 000000000..5cc09dfe3 --- /dev/null +++ b/internal/commandpresentation/presentation_test.go @@ -0,0 +1,85 @@ +package commandpresentation + +import ( + "testing" +) + +func TestDecodeCommandPresentation(t *testing.T) { + t.Parallel() + for _, test := range []struct { + name, operation, body, status, output, failure string + }{ + {name: "submit", operation: "submit", body: `{"text":"answer"}`, output: "answer"}, + {name: "steer", operation: "steer", body: `{"text":"answer"}`, output: "answer"}, + {name: "submit parts", operation: "submit.parts", body: `{"text":"answer"}`, output: "answer"}, + {name: "steer parts", operation: "steer.parts", body: `{"text":"answer"}`, output: "answer"}, + {name: "shell", operation: "shell.run", body: `{"text":"answer"}`, output: "answer"}, + {name: "tool", operation: "tool.call", body: `{"text":"answer"}`, output: "answer"}, + {name: "create", operation: "session.create", body: `{"root_id":"root"}`, output: "root"}, + {name: "open", operation: "session.open", body: `{"root_id":"root"}`, output: "root"}, + {name: "fork", operation: "session.fork", body: `{"root_id":"root"}`, output: "root"}, + {name: "delete", operation: "session.delete", body: `{"root_id":"root"}`, output: "root"}, + {name: "inspect", operation: "workspace.inspect", body: `{"path":"/workspace"}`, output: "/workspace"}, + {name: "set workspace", operation: "workspace.set", body: `{"path":"/workspace"}`, output: "/workspace"}, + {name: "rename", operation: "session.rename", body: `{"title":"title"}`, output: "title"}, + {name: "set goal", operation: "goal.set", body: `{"goal":"goal"}`, output: "goal"}, + {name: "run goal", operation: "goal.run", body: `{"goal":"goal"}`, output: "goal"}, + {name: "derive goal", operation: "goal.from-context", body: `{"goal":"goal"}`, output: "goal"}, + {name: "set effort", operation: "session.effort", body: `{"effort":"high"}`, output: "high"}, + {name: "get effort", operation: "session.effort.get", body: `{"effort":"high"}`, output: "high"}, + {name: "set model", operation: "session.model", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "get model", operation: "session.model.get", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "reload model", operation: "session.reload", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, + {name: "empty success", operation: "submit"}, + {name: "empty failure", operation: "submit", status: "failed"}, + {name: "failed", operation: "submit", body: `{"message":"failure"}`, status: "failed", failure: "failure"}, + {name: "cancelled", operation: "submit", body: `{"message":"failure"}`, status: "cancelled", failure: "failure"}, + {name: "interrupted unknown operation", operation: "unknown", body: `{"message":"failure"}`, status: "interrupted", failure: "failure"}, + {name: "empty failure object", operation: "submit", body: `{}`, status: "failed"}, + {name: "null failure", operation: "submit", body: `null`, status: "failed"}, + {name: "null failure message", operation: "submit", body: `{"message":null}`, status: "failed"}, + {name: "malformed failure", operation: "submit", body: `{`, status: "failed", failure: "invalid structured command failure"}, + {name: "numeric failure message", operation: "submit", body: `{"message":1}`, status: "failed", failure: "invalid structured command failure"}, + {name: "invalid failure code", operation: "submit", body: `{"message":"failure","code":"bad"}`, status: "failed", failure: "invalid structured command failure"}, + {name: "invalid failure data", operation: "submit", body: `{"message":"failure","data":false}`, status: "failed", failure: "invalid structured command failure"}, + {name: "failure field case", operation: "submit", body: `{"MESSAGE":"failure"}`, status: "failed", failure: "failure"}, + {name: "status is case sensitive", operation: "submit", body: `{"text":"answer"}`, status: "FAILED", output: "answer"}, + {name: "ignored field and retained whitespace", operation: "submit", body: `{"text":" answer ","ignored":true}`, output: " answer "}, + {name: "null result field", operation: "submit", body: `{"text":null}`}, + {name: "missing result field", operation: "submit", body: `{}`, failure: "invalid command result field"}, + {name: "null result object", operation: "submit", body: `null`, failure: "invalid command result field"}, + {name: "result field case", operation: "submit", body: `{"Text":"answer"}`, failure: "invalid command result field"}, + {name: "numeric result field", operation: "submit", body: `{"text":1}`, failure: "invalid command result field"}, + {name: "object result field", operation: "submit", body: `{"text":{}}`, failure: "invalid command result field"}, + {name: "array result field", operation: "submit", body: `{"text":[]}`, failure: "invalid command result field"}, + {name: "malformed result", operation: "submit", body: `{`, failure: "invalid command result"}, + {name: "trailing result", operation: "submit", body: `{"text":"a"} {}`, failure: "invalid command result"}, + {name: "scalar result", operation: "submit", body: `"answer"`, failure: "invalid command result"}, + {name: "array result", operation: "submit", body: `[]`, failure: "invalid command result"}, + {name: "duplicate result field", operation: "submit", body: `{"text":"first","text":"last"}`, output: "last"}, + {name: "empty model", operation: "session.model", body: `{}`, output: "@"}, + {name: "null model", operation: "session.model", body: `null`, output: "@"}, + {name: "model only", operation: "session.model", body: `{"model":"m"}`, output: "m @"}, + {name: "provider only", operation: "session.model", body: `{"provider":"p"}`, output: "@ p"}, + {name: "model whitespace", operation: "session.model", body: `{"model":" m ","provider":" p "}`, output: "m @ p"}, + {name: "model field case", operation: "session.model", body: `{"MODEL":"m","PROVIDER":"p"}`, output: "m @ p"}, + {name: "malformed model", operation: "session.model", body: `{`, failure: "invalid model result"}, + {name: "numeric model", operation: "session.model", body: `{"model":1}`, failure: "invalid model result"}, + {name: "numeric provider", operation: "session.model", body: `{"provider":1}`, failure: "invalid model result"}, + {name: "invalid ignored model field", operation: "session.model", body: `{"reload_pending":"yes"}`, failure: "invalid model result"}, + {name: "unknown plain text", operation: "unknown", body: "answer", output: "answer"}, + {name: "unknown malformed json", operation: "unknown", body: `{`, output: `{`}, + {name: "unknown whitespace", operation: "unknown", body: " \n\t ", output: " \n\t "}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + output, failure := Decode(test.operation, []byte(test.body), test.status) + if output != test.output || failure != test.failure { + t.Fatalf("presentation = (%q, %q), want (%q, %q)", output, failure, test.output, test.failure) + } + }) + } + if output, failure := Decode("submit", nil, "failed"); output != "" || failure != "" { + t.Fatalf("nil failure body = (%q, %q)", output, failure) + } +} diff --git a/internal/daemon/acceptance_test.go b/internal/daemon/acceptance_test.go index 95edf78e0..deb5056eb 100644 --- a/internal/daemon/acceptance_test.go +++ b/internal/daemon/acceptance_test.go @@ -17,6 +17,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" @@ -75,7 +76,7 @@ func stopAcceptanceProcess(t *testing.T, process *acceptanceProcess) { } } -func acceptanceClient(t *testing.T, paths RuntimePaths, clientID string, cursors map[string]int64) *Client { +func acceptanceClient(t *testing.T, paths daemonconn.RuntimePaths, clientID string, cursors map[string]int64) *Client { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() @@ -149,7 +150,7 @@ func TestRuntimeAcceptanceDetachedRecoveryAndContextIsolation(t *testing.T) { if err := store.Close(); err != nil { t.Fatal(err) } - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -341,7 +342,7 @@ func TestRuntimeAcceptanceDaemonHelper(t *testing.T) { if err != nil { t.Fatal(err) } - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/architecture_test.go b/internal/daemon/architecture_test.go index 58515abdb..7e083c153 100644 --- a/internal/daemon/architecture_test.go +++ b/internal/daemon/architecture_test.go @@ -80,6 +80,27 @@ func TestArchitectureKeepsProviderIndependentOfDaemon(t *testing.T) { } } +func TestArchitectureKeepsConnectionPlumbingIndependentOfDaemon(t *testing.T) { + root := repositoryRoot(t) + for _, directory := range []string{"daemonconn", "commandpresentation"} { + for path, body := range productionGoFiles(t, filepath.Join(root, "internal", directory)) { + file, err := parser.ParseFile(token.NewFileSet(), path, body, parser.ImportsOnly) + if err != nil { + t.Fatal(err) + } + for _, imported := range file.Imports { + name, err := strconv.Unquote(imported.Path.Value) + if err != nil { + t.Fatal(err) + } + if name == "github.com/context-labs/whip/internal/daemon" { + t.Errorf("connection plumbing imports daemon: %s", path) + } + } + } + } +} + func TestArchitectureKeepsTUIAsDaemonClient(t *testing.T) { root := repositoryRoot(t) for path, body := range productionGoFiles(t, filepath.Join(root, "internal", "tui")) { diff --git a/internal/daemon/autostart.go b/internal/daemon/autostart.go index c5c80118f..e62452ffa 100644 --- a/internal/daemon/autostart.go +++ b/internal/daemon/autostart.go @@ -4,17 +4,19 @@ import ( "context" "errors" "time" + + "github.com/context-labs/whip/internal/daemonconn" ) type LaunchDaemon func() error // EnsureClient attaches to a responsive daemon, starting one when the socket // is missing or stale. Losing launch races simply attach to the winner. -func EnsureClient(ctx context.Context, paths RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { +func EnsureClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { return awaitClient(ctx, paths, initialize, launch) } -func awaitClient(ctx context.Context, paths RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { +func awaitClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { client, err := DialClient(ctx, paths, initialize) if err == nil { return client, nil @@ -22,7 +24,7 @@ func awaitClient(ctx context.Context, paths RuntimePaths, initialize InitializeP if _, rejected := errors.AsType[*RPCError](err); rejected || launch == nil { return nil, err } - if launchErr := launch(); launchErr != nil && !errors.Is(launchErr, ErrDaemonOwned) { + if launchErr := launch(); launchErr != nil && !errors.Is(launchErr, daemonconn.ErrDaemonOwned) { return nil, launchErr } delay := 10 * time.Millisecond diff --git a/internal/daemon/autostart_test.go b/internal/daemon/autostart_test.go index fab08b789..7f5b56086 100644 --- a/internal/daemon/autostart_test.go +++ b/internal/daemon/autostart_test.go @@ -13,6 +13,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -24,7 +25,7 @@ type runningServer struct { func TestEnsureClientStartsDaemonAcrossStaleSocket(t *testing.T) { home := t.TempDir() - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -59,7 +60,7 @@ func TestEnsureClientStartsDaemonAcrossStaleSocket(t *testing.T) { } func TestEnsureClientReportsLaunchAndContextFailures(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -72,70 +73,14 @@ func TestEnsureClientReportsLaunchAndContextFailures(t *testing.T) { } ctx, cancel := context.WithCancel(context.Background()) cancel() - if _, err := EnsureClient(ctx, paths, InitializeParams{}, func() error { return ErrDaemonOwned }); !errors.Is(err, context.Canceled) { + if _, err := EnsureClient(ctx, paths, InitializeParams{}, func() error { return daemonconn.ErrDaemonOwned }); !errors.Is(err, context.Canceled) { t.Fatalf("cancelled autostart = %v", err) } } -func TestLaunchDaemonProcessUsesOwnerOnlyLog(t *testing.T) { - paths, err := Paths(t.TempDir()) - if err != nil { - t.Fatal(err) - } - if err := launchDaemonProcess(paths, "/usr/bin/true"); err != nil { - t.Fatal(err) - } - info, err := os.Stat(filepath.Join(paths.Home, "daemon.log")) - if err != nil || info.Mode().Perm() != 0o600 { - t.Fatalf("daemon log mode = %v, %v", info, err) - } -} - -func TestSelfLaunchAndRestartUseCurrentExecutable(t *testing.T) { - previousExecutable, previousReplace := selfExecutable, replaceProcess - selfExecutable = func() (string, error) { return "/usr/bin/true", nil } - var replaced bool - - replaceProcess = func(path string, args, _ []string) error { - replaced = path == "/usr/bin/true" && len(args) == 2 && args[1] == "_daemon" - return errors.New("exec stopped for test") - } - t.Cleanup(func() { selfExecutable, replaceProcess = previousExecutable, previousReplace }) - paths, err := Paths(t.TempDir()) - if err != nil { - t.Fatal(err) - } - if err := LaunchSelfDaemon(paths); err != nil { - t.Fatal(err) - } - if err := RestartSelfDaemon(); err == nil || !replaced { - t.Fatalf("restart replacement = %v, called=%t", err, replaced) - } -} - -func TestSelfLaunchAndRestartReportExecutableFailures(t *testing.T) { - previousExecutable := selfExecutable - want := errors.New("executable unavailable") - selfExecutable = func() (string, error) { return "", want } - t.Cleanup(func() { selfExecutable = previousExecutable }) - paths, err := Paths(t.TempDir()) - if err != nil { - t.Fatal(err) - } - if err := LaunchSelfDaemon(paths); !errors.Is(err, want) { - t.Fatalf("launch executable error = %v", err) - } - if err := RestartSelfDaemon(); !errors.Is(err, want) { - t.Fatalf("restart executable error = %v", err) - } - if err := launchDaemonProcess(paths, filepath.Join(t.TempDir(), "missing")); err == nil { - t.Fatal("missing daemon executable launched") - } -} - func TestEnsureClientAttachesAcrossBuildsWithoutRestart(t *testing.T) { home := t.TempDir() - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -164,7 +109,7 @@ func TestEnsureClientAttachesAcrossBuildsWithoutRestart(t *testing.T) { func TestEnsureClientRejectsOldProtocolWithoutLaunching(t *testing.T) { home := t.TempDir() - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -186,7 +131,7 @@ func TestEnsureClientRejectsOldProtocolWithoutLaunching(t *testing.T) { } } -func startTestServer(path string, paths RuntimePaths, buildID string, generation int64, restart func()) (runningServer, error) { +func startTestServer(path string, paths daemonconn.RuntimePaths, buildID string, generation int64, restart func()) (runningServer, error) { store, err := session.Open(path, capability.NewWorkspaces()) if err != nil { return runningServer{}, err diff --git a/internal/daemon/client.go b/internal/daemon/client.go index c5c25ba3a..44432e304 100644 --- a/internal/daemon/client.go +++ b/internal/daemon/client.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -43,15 +44,15 @@ type Client struct { once sync.Once } -func DialClient(ctx context.Context, paths RuntimePaths, initialize InitializeParams) (*Client, error) { - timeout := initializationTimeout +func DialClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams) (*Client, error) { + timeout := daemonconn.InitializationTimeout if deadline, ok := ctx.Deadline(); ok { timeout = time.Until(deadline) if timeout <= 0 { return nil, ctx.Err() } } - conn, err := dialLocal(paths, timeout) + conn, err := daemonconn.DialLocal(paths, timeout) if err != nil { return nil, err } @@ -86,7 +87,7 @@ func newTransportClient(ctx context.Context, conn messageTransport, initialize I if err != nil { return nil, err } - deadline := time.Now().Add(initializationTimeout) + deadline := time.Now().Add(daemonconn.InitializationTimeout) if contextDeadline, ok := ctx.Deadline(); ok && contextDeadline.Before(deadline) { deadline = contextDeadline } @@ -384,7 +385,7 @@ func (c *Client) readLoop() { return } if message.Method == "event" { - var notification eventNotification + var notification daemonconn.EventNotification if err := json.Unmarshal(message.Params, ¬ification); err != nil { c.close(err) return diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index f27b168e3..f291d3464 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -15,14 +15,17 @@ import ( "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/browser" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/commandpresentation" "github.com/context-labs/whip/internal/computer" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/lsp" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/schedule" + sessionstore "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" ) @@ -391,7 +394,7 @@ func (s *Session) clientCommand(ctx context.Context, admission sessionstore.Comm return finish(resolveErr) } result.Result = body - result.Output, result.Error = decodeCommandPresentation(operation, body, admitted.Command.Status) + result.Output, result.Error = commandpresentation.Decode(operation, body, admitted.Command.Status) return finish(nil) } completionReply := make(chan clientCommandReply, 1) @@ -773,7 +776,7 @@ func (s *Session) finishClientCommandInline(ctx context.Context, admission sessi return errors.Join(actionErr, finishErr) } result.Status, result.Operation, result.Result = status, operation, body - result.Output, result.Error = decodeCommandPresentation(operation, body, status) + result.Output, result.Error = commandpresentation.Decode(operation, body, status) return nil } diff --git a/internal/daemon/command_outcome.go b/internal/daemon/command_outcome.go index 5000b1b25..d611524ac 100644 --- a/internal/daemon/command_outcome.go +++ b/internal/daemon/command_outcome.go @@ -2,8 +2,8 @@ package daemon import ( "encoding/json" - "strings" + "github.com/context-labs/whip/internal/commandpresentation" "github.com/context-labs/whip/internal/protocol" ) @@ -54,56 +54,8 @@ func encodeTurnOutcome(text string, output json.RawMessage, failure error) []byt return body } -// decodeCommandPresentation formats only v2 structured outcomes for existing -// text presenters. It never accepts an old plain-text stored outcome. -func decodeCommandPresentation(operation string, body []byte, status string) (string, string) { - if len(body) == 0 { - return "", "" - } - if status == "failed" || status == "cancelled" || status == "interrupted" { - var failure RPCError - if err := json.Unmarshal(body, &failure); err != nil { - return "", "invalid structured command failure" - } - return "", failure.Message - } - field := "" - switch operation { - case "submit", "steer", "submit.parts", "steer.parts", "shell.run", "tool.call": - field = "text" - case "session.create", "session.open", "session.fork", "session.delete": - field = "root_id" - case "workspace.inspect", "workspace.set": - field = "path" - case "session.rename": - field = "title" - case "goal.set", "goal.run", "goal.from-context": - field = "goal" - case "session.effort", "session.effort.get": - field = "effort" - case "session.model", "session.model.get", "session.reload": - var result protocol.ModelResult - if err := json.Unmarshal(body, &result); err != nil { - return "", "invalid model result" - } - return strings.TrimSpace(result.Model + " @ " + result.Provider), "" - } - if field != "" { - var values map[string]json.RawMessage - if json.Unmarshal(body, &values) != nil { - return "", "invalid command result" - } - var text string - if json.Unmarshal(values[field], &text) != nil { - return "", "invalid command result field" - } - return text, "" - } - return string(body), "" -} - func fillCommandPresentation(result *CommandResult) { - result.Output, result.Error = decodeCommandPresentation(result.Operation, result.Result, result.Status) + result.Output, result.Error = commandpresentation.Decode(result.Operation, result.Result, result.Status) if result.Failure != nil { result.Error = result.Failure.Message } diff --git a/internal/daemon/command_outcome_test.go b/internal/daemon/command_outcome_test.go index 1a9a59010..778c3798a 100644 --- a/internal/daemon/command_outcome_test.go +++ b/internal/daemon/command_outcome_test.go @@ -2,86 +2,6 @@ package daemon import "testing" -func TestDecodeCommandPresentation(t *testing.T) { - t.Parallel() - for _, test := range []struct { - name, operation, body, status, output, failure string - }{ - {name: "submit", operation: "submit", body: `{"text":"answer"}`, output: "answer"}, - {name: "steer", operation: "steer", body: `{"text":"answer"}`, output: "answer"}, - {name: "submit parts", operation: "submit.parts", body: `{"text":"answer"}`, output: "answer"}, - {name: "steer parts", operation: "steer.parts", body: `{"text":"answer"}`, output: "answer"}, - {name: "shell", operation: "shell.run", body: `{"text":"answer"}`, output: "answer"}, - {name: "tool", operation: "tool.call", body: `{"text":"answer"}`, output: "answer"}, - {name: "create", operation: "session.create", body: `{"root_id":"root"}`, output: "root"}, - {name: "open", operation: "session.open", body: `{"root_id":"root"}`, output: "root"}, - {name: "fork", operation: "session.fork", body: `{"root_id":"root"}`, output: "root"}, - {name: "delete", operation: "session.delete", body: `{"root_id":"root"}`, output: "root"}, - {name: "inspect", operation: "workspace.inspect", body: `{"path":"/workspace"}`, output: "/workspace"}, - {name: "set workspace", operation: "workspace.set", body: `{"path":"/workspace"}`, output: "/workspace"}, - {name: "rename", operation: "session.rename", body: `{"title":"title"}`, output: "title"}, - {name: "set goal", operation: "goal.set", body: `{"goal":"goal"}`, output: "goal"}, - {name: "run goal", operation: "goal.run", body: `{"goal":"goal"}`, output: "goal"}, - {name: "derive goal", operation: "goal.from-context", body: `{"goal":"goal"}`, output: "goal"}, - {name: "set effort", operation: "session.effort", body: `{"effort":"high"}`, output: "high"}, - {name: "get effort", operation: "session.effort.get", body: `{"effort":"high"}`, output: "high"}, - {name: "set model", operation: "session.model", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, - {name: "get model", operation: "session.model.get", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, - {name: "reload model", operation: "session.reload", body: `{"model":"m","provider":"p"}`, output: "m @ p"}, - {name: "empty success", operation: "submit"}, - {name: "empty failure", operation: "submit", status: "failed"}, - {name: "failed", operation: "submit", body: `{"message":"failure"}`, status: "failed", failure: "failure"}, - {name: "cancelled", operation: "submit", body: `{"message":"failure"}`, status: "cancelled", failure: "failure"}, - {name: "interrupted unknown operation", operation: "unknown", body: `{"message":"failure"}`, status: "interrupted", failure: "failure"}, - {name: "empty failure object", operation: "submit", body: `{}`, status: "failed"}, - {name: "null failure", operation: "submit", body: `null`, status: "failed"}, - {name: "null failure message", operation: "submit", body: `{"message":null}`, status: "failed"}, - {name: "malformed failure", operation: "submit", body: `{`, status: "failed", failure: "invalid structured command failure"}, - {name: "numeric failure message", operation: "submit", body: `{"message":1}`, status: "failed", failure: "invalid structured command failure"}, - {name: "invalid failure code", operation: "submit", body: `{"message":"failure","code":"bad"}`, status: "failed", failure: "invalid structured command failure"}, - {name: "invalid failure data", operation: "submit", body: `{"message":"failure","data":false}`, status: "failed", failure: "invalid structured command failure"}, - {name: "failure field case", operation: "submit", body: `{"MESSAGE":"failure"}`, status: "failed", failure: "failure"}, - {name: "status is case sensitive", operation: "submit", body: `{"text":"answer"}`, status: "FAILED", output: "answer"}, - {name: "ignored field and retained whitespace", operation: "submit", body: `{"text":" answer ","ignored":true}`, output: " answer "}, - {name: "null result field", operation: "submit", body: `{"text":null}`}, - {name: "missing result field", operation: "submit", body: `{}`, failure: "invalid command result field"}, - {name: "null result object", operation: "submit", body: `null`, failure: "invalid command result field"}, - {name: "result field case", operation: "submit", body: `{"Text":"answer"}`, failure: "invalid command result field"}, - {name: "numeric result field", operation: "submit", body: `{"text":1}`, failure: "invalid command result field"}, - {name: "object result field", operation: "submit", body: `{"text":{}}`, failure: "invalid command result field"}, - {name: "array result field", operation: "submit", body: `{"text":[]}`, failure: "invalid command result field"}, - {name: "malformed result", operation: "submit", body: `{`, failure: "invalid command result"}, - {name: "trailing result", operation: "submit", body: `{"text":"a"} {}`, failure: "invalid command result"}, - {name: "scalar result", operation: "submit", body: `"answer"`, failure: "invalid command result"}, - {name: "array result", operation: "submit", body: `[]`, failure: "invalid command result"}, - {name: "duplicate result field", operation: "submit", body: `{"text":"first","text":"last"}`, output: "last"}, - {name: "empty model", operation: "session.model", body: `{}`, output: "@"}, - {name: "null model", operation: "session.model", body: `null`, output: "@"}, - {name: "model only", operation: "session.model", body: `{"model":"m"}`, output: "m @"}, - {name: "provider only", operation: "session.model", body: `{"provider":"p"}`, output: "@ p"}, - {name: "model whitespace", operation: "session.model", body: `{"model":" m ","provider":" p "}`, output: "m @ p"}, - {name: "model field case", operation: "session.model", body: `{"MODEL":"m","PROVIDER":"p"}`, output: "m @ p"}, - {name: "malformed model", operation: "session.model", body: `{`, failure: "invalid model result"}, - {name: "numeric model", operation: "session.model", body: `{"model":1}`, failure: "invalid model result"}, - {name: "numeric provider", operation: "session.model", body: `{"provider":1}`, failure: "invalid model result"}, - {name: "invalid ignored model field", operation: "session.model", body: `{"reload_pending":"yes"}`, failure: "invalid model result"}, - {name: "unknown plain text", operation: "unknown", body: "answer", output: "answer"}, - {name: "unknown malformed json", operation: "unknown", body: `{`, output: `{`}, - {name: "unknown whitespace", operation: "unknown", body: " \n\t ", output: " \n\t "}, - } { - t.Run(test.name, func(t *testing.T) { - t.Parallel() - output, failure := decodeCommandPresentation(test.operation, []byte(test.body), test.status) - if output != test.output || failure != test.failure { - t.Fatalf("presentation = (%q, %q), want (%q, %q)", output, failure, test.output, test.failure) - } - }) - } - if output, failure := decodeCommandPresentation("submit", nil, "failed"); output != "" || failure != "" { - t.Fatalf("nil failure body = (%q, %q)", output, failure) - } -} - func TestFillCommandPresentation(t *testing.T) { t.Parallel() for _, test := range []struct { diff --git a/internal/daemon/control.go b/internal/daemon/control.go index 90c30dafc..ed5559604 100644 --- a/internal/daemon/control.go +++ b/internal/daemon/control.go @@ -74,22 +74,7 @@ func (c *Control) route(ctx context.Context, work func(context.Context) error) e return <-request.done } -type CreateSession struct { - ExecutionEngine string `json:"execution_engine,omitempty"` - // Definition selects the agent definition; empty means the coding agent. - // DefinitionRevision is pinned by the daemon for registered definitions and - // is not accepted from clients. - Definition string `json:"definition,omitempty"` - DefinitionRevision string `json:"definition_revision,omitempty"` - Kind session.SessionKind `json:"kind"` - CWD string `json:"cwd"` - Model string `json:"model"` - Provider string `json:"provider"` - // Effort is "off" or a catalog level. Blank asks the daemon to resolve the - // definition's default, else the configured default, against the model. - Effort string `json:"effort,omitempty"` - PermissionMode string `json:"permission_mode,omitempty"` -} +type CreateSession = session.CreateSession func (c *Control) CreateSession(ctx context.Context, admission session.CommandAdmission, create CreateSession) (record session.CommandRecord, err error) { err = c.route(ctx, func(actorCtx context.Context) error { diff --git a/internal/daemon/gateway_test.go b/internal/daemon/gateway_test.go index dab64b809..b97988696 100644 --- a/internal/daemon/gateway_test.go +++ b/internal/daemon/gateway_test.go @@ -5,11 +5,12 @@ import ( "crypto/rand" "testing" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webgateway" ) -func startTestGateway(t *testing.T, paths RuntimePaths, options webgateway.Options) *webgateway.Server { +func startTestGateway(t *testing.T, paths daemonconn.RuntimePaths, options webgateway.Options) *webgateway.Server { t.Helper() if options.Address == "" { options.Address = "127.0.0.1:0" diff --git a/internal/daemon/maintenance_unix.go b/internal/daemon/maintenance_unix.go index 2638156d5..d8449b6db 100644 --- a/internal/daemon/maintenance_unix.go +++ b/internal/daemon/maintenance_unix.go @@ -9,12 +9,13 @@ import ( "path/filepath" "syscall" + "github.com/context-labs/whip/internal/daemonconn" "golang.org/x/sys/unix" ) var ErrMaintenance = errors.New("whipcode is applying a backend update; retry after it finishes") -func maintenanceFile(paths RuntimePaths) (*os.File, error) { +func maintenanceFile(paths daemonconn.RuntimePaths) (*os.File, error) { name := filepath.Join(paths.Runtime, "maintenance.lock") fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC|unix.O_NOFOLLOW, 0o600) if err != nil { @@ -36,7 +37,7 @@ func maintenanceFile(paths RuntimePaths) (*os.File, error) { // AcquireMaintenance excludes daemon starts and other updaters until Close. // Never unlink this file: every participant must lock the same inode. -func AcquireMaintenance(paths RuntimePaths) (*os.File, error) { +func AcquireMaintenance(paths daemonconn.RuntimePaths) (*os.File, error) { file, err := maintenanceFile(paths) if err != nil { return nil, err @@ -51,7 +52,7 @@ func AcquireMaintenance(paths RuntimePaths) (*os.File, error) { // AcquireStartup fences owner acquisition. Ordinary starts fail rather than // waiting with an old executable mapped. An updater may pass its held lock to // the replacement child; Close must not explicitly unlock that shared descriptor. -func AcquireStartup(paths RuntimePaths, inheritedFD int) (*os.File, error) { +func AcquireStartup(paths daemonconn.RuntimePaths, inheritedFD int) (*os.File, error) { file, err := maintenanceFile(paths) if err != nil { return nil, err diff --git a/internal/daemon/maintenance_unix_test.go b/internal/daemon/maintenance_unix_test.go index b1b730f04..9ec70995a 100644 --- a/internal/daemon/maintenance_unix_test.go +++ b/internal/daemon/maintenance_unix_test.go @@ -9,11 +9,12 @@ import ( "path/filepath" "testing" + "github.com/context-labs/whip/internal/daemonconn" "golang.org/x/sys/unix" ) func TestMaintenanceExcludesStartsAndOtherUpdaters(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -56,7 +57,7 @@ func TestMaintenanceExcludesStartsAndOtherUpdaters(t *testing.T) { func TestMaintenanceInheritedDescriptor(t *testing.T) { if home := os.Getenv("WHIP_MAINTENANCE_CHILD"); home != "" { - paths, err := ResolvePaths(home) + paths, err := daemonconn.ResolvePaths(home) if err != nil { t.Fatal(err) } @@ -73,7 +74,7 @@ func TestMaintenanceInheritedDescriptor(t *testing.T) { return } home := t.TempDir() - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } @@ -98,7 +99,7 @@ func TestMaintenanceInheritedDescriptor(t *testing.T) { func TestMaintenanceRefusesMissingInheritedDescriptor(t *testing.T) { if home := os.Getenv("WHIP_MAINTENANCE_MISSING_CHILD"); home != "" { - paths, err := ResolvePaths(home) + paths, err := daemonconn.ResolvePaths(home) if err != nil { t.Fatal(err) } @@ -120,7 +121,7 @@ func TestMaintenanceRefusesMissingInheritedDescriptor(t *testing.T) { return } home := t.TempDir() - if _, err := Paths(home); err != nil { + if _, err := daemonconn.Paths(home); err != nil { t.Fatal(err) } sentinel, err := os.CreateTemp(t.TempDir(), "sentinel") @@ -137,7 +138,7 @@ func TestMaintenanceRefusesMissingInheritedDescriptor(t *testing.T) { } func TestMaintenanceRefusesSymlinkAndForeignDescriptor(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -161,7 +162,7 @@ func TestMaintenanceRefusesSymlinkAndForeignDescriptor(t *testing.T) { func TestMaintenanceRefusesUnsafeExistingLock(t *testing.T) { for _, kind := range []string{"shared", "directory", "missing-parent"} { t.Run(kind, func(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -191,7 +192,7 @@ func TestMaintenanceRefusesUnsafeExistingLock(t *testing.T) { } func TestMaintenanceLaunchFailuresReleaseResources(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -200,11 +201,11 @@ func TestMaintenanceLaunchFailuresReleaseResources(t *testing.T) { t.Fatal(err) } defer maintenance.Close() - if err := LaunchInstalledDaemon(paths, filepath.Join(paths.Home, "missing-executable"), maintenance); err == nil { + if err := daemonconn.LaunchInstalledDaemon(paths, filepath.Join(paths.Home, "missing-executable"), maintenance); err == nil { t.Fatal("missing executable started") } paths.Home = filepath.Join(paths.Home, "missing-parent") - if err := LaunchInstalledDaemon(paths, "/bin/false", maintenance); err == nil { + if err := daemonconn.LaunchInstalledDaemon(paths, "/bin/false", maintenance); err == nil { t.Fatal("missing log directory accepted") } } @@ -212,7 +213,7 @@ func TestMaintenanceLaunchFailuresReleaseResources(t *testing.T) { func TestMaintenanceValidatesInheritedOpenFileDescription(t *testing.T) { for _, kind := range []string{"shared-description", "wrong-file", "closed", "unlocked", "independent-description"} { t.Run(kind, func(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/protocol.go b/internal/daemon/protocol.go index d90251a2a..140cb33e4 100644 --- a/internal/daemon/protocol.go +++ b/internal/daemon/protocol.go @@ -8,9 +8,9 @@ import ( "errors" "io" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/protocoltransport" - "github.com/context-labs/whip/internal/session" ) @@ -19,10 +19,10 @@ const ( ProtocolMinor = protocol.Minor MaxSubscriptions = 16 MaxFrameSize = protocoltransport.MaxFrameSize - MaxContentChunk = 256 << 10 + MaxContentChunk = daemonconn.MaxContentChunk MaxConnections = 64 MaxInFlight = 32 - MaxOutboundEnvelopes = 1024 + MaxOutboundEnvelopes = daemonconn.MaxOutboundEnvelopes MaxOutboundBytes = 8 << 20 MaxUploadSize = session.MaxInputPayloadBytes ) @@ -108,10 +108,6 @@ type RestartNotice = protocol.RestartNotice type RestartParams = protocol.RestartParams -type eventNotification struct { - Event ProtocolEvent `json:"event"` -} - func requestDigest(scope, rootID, operation string, payload json.RawMessage) (string, error) { var value any if len(payload) == 0 { diff --git a/internal/daemon/protocol_edge_test.go b/internal/daemon/protocol_edge_test.go index bb0d98caf..df5dda107 100644 --- a/internal/daemon/protocol_edge_test.go +++ b/internal/daemon/protocol_edge_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/session" ) @@ -157,7 +158,7 @@ func TestClientConnectionAndReadLoopFailures(t *testing.T) { frames := map[string]rpcMessage{ "invalid event": {Method: "event", Params: json.RawMessage(`true`)}, - "event overflow": {Method: "event", Params: mustJSON(t, eventNotification{Event: ProtocolEvent{RootID: "root", Seq: 2}})}, + "event overflow": {Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: ProtocolEvent{RootID: "root", Seq: 2}})}, "orphan reply": {ID: json.RawMessage("99"), Result: true}, } for name, message := range frames { diff --git a/internal/daemon/server.go b/internal/daemon/server.go index 3239222e8..41f6e7d3e 100644 --- a/internal/daemon/server.go +++ b/internal/daemon/server.go @@ -18,15 +18,17 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/commandpresentation" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" ) const ( - initializationTimeout = 5 * time.Second - clientIdleTimeout = 90 * time.Second + clientIdleTimeout = 90 * time.Second ) type ServerOptions struct { @@ -108,7 +110,7 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { options.MaxOutboundBytes = MaxOutboundBytes } if options.InitializationTimeout <= 0 { - options.InitializationTimeout = initializationTimeout + options.InitializationTimeout = daemonconn.InitializationTimeout } if options.ClientIdleTimeout <= 0 { options.ClientIdleTimeout = clientIdleTimeout @@ -140,7 +142,7 @@ func NewServer(value *Daemon, options ServerOptions) (*Server, error) { return server, nil } -func (s *Server) ListenAndServe(paths RuntimePaths) error { +func (s *Server) ListenAndServe(paths daemonconn.RuntimePaths) error { listener, err := listenLocal(paths) if err != nil { return err @@ -770,7 +772,7 @@ func (s *Server) commandRecordResult(ctx context.Context, record session.Command } else if len(output) > 0 { result.Result = json.RawMessage(output) } - result.Output, result.Error = decodeCommandPresentation(record.Operation, output, record.Status) + result.Output, result.Error = commandpresentation.Decode(record.Operation, output, record.Status) return result, errors.Join(actionErr, resolveErr) } diff --git a/internal/daemon/session.go b/internal/daemon/session.go index 60bc5634f..0a40e69d0 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -15,11 +15,14 @@ import ( "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/agentdef" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/commandpresentation" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" + sessionstore "github.com/context-labs/whip/internal/session" ) @@ -459,10 +462,10 @@ func (s *Session) admitCommand(ctx context.Context, admission sessionstore.Comma if resolveErr != nil { receipt.finish(Completion{Sequence: result.Command.IngressSeq, Err: resolveErr}) } else if result.Command.Status == "succeeded" { - text, _ := decodeCommandPresentation(result.Command.Operation, output, result.Command.Status) + text, _ := commandpresentation.Decode(result.Command.Operation, output, result.Command.Status) receipt.finish(Completion{Sequence: result.Command.IngressSeq, Output: text}) } else { - _, message := decodeCommandPresentation(result.Command.Operation, output, result.Command.Status) + _, message := commandpresentation.Decode(result.Command.Operation, output, result.Command.Status) if message == "" { message = "command is " + result.Command.Status } diff --git a/internal/daemon/socket_unix.go b/internal/daemon/socket_unix.go index 590a7aa32..d16173ab4 100644 --- a/internal/daemon/socket_unix.go +++ b/internal/daemon/socket_unix.go @@ -4,72 +4,20 @@ package daemon import ( "context" - "crypto/sha256" - "encoding/hex" "errors" - "fmt" "io" "net" "os" - "path/filepath" "strconv" "strings" - "syscall" "time" + "github.com/context-labs/whip/internal/daemonconn" "golang.org/x/sys/unix" ) -const maxUnixSocketPath = 100 - -var ErrDaemonOwned = errors.New("another daemon owns this runtime") - -type RuntimePaths struct { - Home string - Runtime string - Socket string - Lock string -} - type OwnerLock struct{ file *os.File } -func Paths(home string) (RuntimePaths, error) { - paths, err := ResolvePaths(home) - if err != nil { - return RuntimePaths{}, err - } - for _, dir := range []string{paths.Home, paths.Runtime} { - if err := os.MkdirAll(dir, 0o700); err != nil { - return RuntimePaths{}, err - } - if err := os.Chmod(dir, 0o700); err != nil { //nolint:gosec // directories require execute permission and remain owner-only. - return RuntimePaths{}, err - } - } - return paths, nil -} - -// ResolvePaths computes daemon locations without creating or modifying them. -// Discovery must use this instead of Paths so inspecting a stopped installation -// does not initialize a runtime or change existing directory permissions. -func ResolvePaths(home string) (RuntimePaths, error) { - if home == "" { - return RuntimePaths{}, errors.New("runtime home is required") - } - abs, err := filepath.Abs(filepath.Join(home, "runtime-v2")) - if err != nil { - return RuntimePaths{}, err - } - runtimeDir := abs - socket := filepath.Join(runtimeDir, "daemon.sock") - if len(socket) >= maxUnixSocketPath { - digest := sha256.Sum256([]byte(abs)) - runtimeDir = filepath.Join(os.TempDir(), fmt.Sprintf("whip-%d-%s", os.Getuid(), hex.EncodeToString(digest[:8]))) - socket = filepath.Join(runtimeDir, "daemon.sock") - } - return RuntimePaths{Home: abs, Runtime: runtimeDir, Socket: socket, Lock: filepath.Join(runtimeDir, "daemon.lock")}, nil -} - // AcquireOwner must run before opening or inspecting sessions.db. func AcquireOwner(path string) (*OwnerLock, error) { file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600) //nolint:gosec // path comes from validated RuntimePaths. @@ -83,7 +31,7 @@ func AcquireOwner(path string) (*OwnerLock, error) { if err := unix.Flock(int(file.Fd()), unix.LOCK_EX|unix.LOCK_NB); err != nil { _ = file.Close() if errors.Is(err, unix.EWOULDBLOCK) { - return nil, ErrDaemonOwned + return nil, daemonconn.ErrDaemonOwned } return nil, err } @@ -144,10 +92,10 @@ func (l *OwnerLock) Close() error { return err } -func listenLocal(paths RuntimePaths) (net.Listener, error) { +func listenLocal(paths daemonconn.RuntimePaths) (net.Listener, error) { if conn, err := (&net.Dialer{Timeout: 150 * time.Millisecond}).DialContext(context.Background(), "unix", paths.Socket); err == nil { _ = conn.Close() - return nil, ErrDaemonOwned + return nil, daemonconn.ErrDaemonOwned } if err := os.Remove(paths.Socket); err != nil && !errors.Is(err, os.ErrNotExist) { return nil, err @@ -163,18 +111,3 @@ func listenLocal(paths RuntimePaths) (net.Listener, error) { } return listener, nil } - -func dialLocal(paths RuntimePaths, timeout time.Duration) (net.Conn, error) { - info, err := os.Lstat(paths.Socket) - if err != nil { - return nil, err - } - if info.Mode()&os.ModeSocket == 0 || info.Mode().Perm() != 0o600 { - return nil, errors.New("daemon socket is not owner-only") - } - stat, ok := info.Sys().(*syscall.Stat_t) - if !ok || int(stat.Uid) != os.Getuid() { - return nil, errors.New("daemon socket has a different owner") - } - return (&net.Dialer{Timeout: timeout}).DialContext(context.Background(), "unix", paths.Socket) -} diff --git a/internal/daemon/socket_unix_test.go b/internal/daemon/socket_unix_test.go index c4523e868..862bdd44f 100644 --- a/internal/daemon/socket_unix_test.go +++ b/internal/daemon/socket_unix_test.go @@ -11,17 +11,19 @@ import ( "strings" "testing" "time" + + "github.com/context-labs/whip/internal/daemonconn" ) func TestRuntimePathsAndOwnerLock(t *testing.T) { - if _, err := Paths(""); err == nil { + if _, err := daemonconn.Paths(""); err == nil { t.Fatal("empty runtime home was accepted") } blocked := filepath.Join(t.TempDir(), "file") if err := os.WriteFile(blocked, []byte("x"), 0o600); err != nil { t.Fatal(err) } - if _, err := Paths(blocked); err == nil { + if _, err := daemonconn.Paths(blocked); err == nil { t.Fatal("regular file was accepted as runtime home") } if _, err := AcquireOwner(filepath.Join(t.TempDir(), "missing", "daemon.lock")); err == nil { @@ -32,11 +34,11 @@ func TestRuntimePathsAndOwnerLock(t *testing.T) { t.Fatal(err) } home := filepath.Join(t.TempDir(), strings.Repeat("long", 40)) - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } - if len(paths.Socket) >= maxUnixSocketPath || paths.Runtime == paths.Home { + if len(paths.Socket) >= 100 || paths.Runtime == paths.Home { t.Fatalf("long-path fallback = %+v", paths) } lock, err := AcquireOwner(paths.Lock) @@ -47,7 +49,7 @@ func TestRuntimePathsAndOwnerLock(t *testing.T) { if err != nil || !active || pid != os.Getpid() { t.Fatalf("active owner = pid %d, active %t, err %v", pid, active, err) } - if _, err := AcquireOwner(paths.Lock); !errors.Is(err, ErrDaemonOwned) { + if _, err := AcquireOwner(paths.Lock); !errors.Is(err, daemonconn.ErrDaemonOwned) { t.Fatalf("second owner error = %v", err) } if err := lock.Close(); err != nil { @@ -63,46 +65,6 @@ func TestRuntimePathsAndOwnerLock(t *testing.T) { _ = lock.Close() } -func TestResolvePathsDoesNotCreateRuntime(t *testing.T) { - t.Parallel() - root, err := os.MkdirTemp("/tmp", "whip-paths-") //nolint:usetesting // Exercise both short and hashed Unix socket paths on macOS. - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = os.RemoveAll(root) }) - for _, test := range []struct { - name string - home string - fallback bool - }{ - {name: "short path", home: filepath.Join(root, "home")}, - {name: "long path", home: filepath.Join(root, strings.Repeat("long", 40)), fallback: true}, - } { - t.Run(test.name, func(t *testing.T) { - t.Parallel() - paths, err := ResolvePaths(test.home) - if err != nil { - t.Fatal(err) - } - if (paths.Runtime != paths.Home) != test.fallback { - t.Fatalf("runtime fallback = %+v", paths) - } - for _, path := range []string{test.home, paths.Home, paths.Runtime} { - if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) { - t.Fatalf("resolving paths touched %s: %v", path, err) - } - } - created, err := Paths(test.home) - if test.fallback { - t.Cleanup(func() { _ = os.RemoveAll(paths.Runtime) }) - } - if err != nil || created != paths { - t.Fatalf("startup and discovery resolved different paths: %+v, %+v, %v", paths, created, err) - } - }) - } -} - func TestActiveOwnerPIDDoesNotCreateOrModifyLock(t *testing.T) { t.Parallel() for _, test := range []struct { @@ -161,7 +123,7 @@ func TestActiveOwnerPIDRejectsMissingOwnerMetadata(t *testing.T) { } func TestOwnerOnlySocketRefusesUnsafeState(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -170,10 +132,10 @@ func TestOwnerOnlySocketRefusesUnsafeState(t *testing.T) { t.Fatal(err) } t.Cleanup(func() { _ = listener.Close(); _ = os.Remove(paths.Socket) }) - if _, err := listenLocal(paths); !errors.Is(err, ErrDaemonOwned) { + if _, err := listenLocal(paths); !errors.Is(err, daemonconn.ErrDaemonOwned) { t.Fatalf("responsive daemon replacement = %v", err) } - conn, err := dialLocal(paths, time.Second) + conn, err := daemonconn.DialLocal(paths, time.Second) if err != nil { t.Fatal(err) } @@ -181,7 +143,7 @@ func TestOwnerOnlySocketRefusesUnsafeState(t *testing.T) { if err := os.Chmod(paths.Socket, 0o666); err != nil { t.Fatal(err) } - if _, err := dialLocal(paths, time.Second); err == nil { + if _, err := daemonconn.DialLocal(paths, time.Second); err == nil { t.Fatal("world-accessible socket should be rejected") } if conn, err := (&net.Dialer{Timeout: time.Second}).DialContext(context.Background(), "unix", paths.Socket); err != nil { @@ -192,7 +154,7 @@ func TestOwnerOnlySocketRefusesUnsafeState(t *testing.T) { } func TestListenLocalReportsStalePathFailures(t *testing.T) { - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } @@ -210,7 +172,7 @@ func TestListenLocalReportsStalePathFailures(t *testing.T) { if _, err := listenLocal(paths); err == nil { t.Fatal("socket was created through a missing directory") } - if _, err := dialLocal(paths, time.Millisecond); err == nil { + if _, err := daemonconn.DialLocal(paths, time.Millisecond); err == nil { t.Fatal("missing socket was dialed") } } diff --git a/internal/daemon/subscription.go b/internal/daemon/subscription.go index b0efb655f..d2953018d 100644 --- a/internal/daemon/subscription.go +++ b/internal/daemon/subscription.go @@ -6,8 +6,8 @@ import ( "errors" "time" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/session" ) @@ -101,7 +101,7 @@ func (s *Server) pumpSubscription(ctx context.Context, c *serverConn, sub *subsc return } event.SubscriptionID = sub.id - if !c.notify("event", eventNotification{Event: event}) { + if !c.notify("event", daemonconn.EventNotification{Event: event}) { return } cursor = event.Seq diff --git a/internal/daemon/subscription_lifecycle_test.go b/internal/daemon/subscription_lifecycle_test.go index f050686e8..7b5b98fe6 100644 --- a/internal/daemon/subscription_lifecycle_test.go +++ b/internal/daemon/subscription_lifecycle_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" ) @@ -14,7 +15,7 @@ func TestClientIgnoresFailureFromReplacedSubscription(t *testing.T) { serverSide, clientSide := net.Pipe() defer func() { _ = serverSide.Close(); _ = clientSide.Close() }() stale, _ := marshalFrame(rpcMessage{Method: "subscription.failed", Params: mustJSON(t, protocol.SubscriptionFailure{RootID: "root", SubscriptionID: "old", Error: rpcFailure(-32010, "expired old stream")})}) - current, _ := marshalFrame(rpcMessage{Method: "event", Params: mustJSON(t, eventNotification{Event: ProtocolEvent{RootID: "root", SubscriptionID: "new", Seq: 4, Kind: "turn.started", Payload: []byte(`{}`)}})}) + current, _ := marshalFrame(rpcMessage{Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: ProtocolEvent{RootID: "root", SubscriptionID: "new", Seq: 4, Kind: "turn.started", Payload: []byte(`{}`)}})}) transport := newUnixMessageTransport(clientSide) written := make(chan struct{}) go func() { diff --git a/internal/daemon/v2_acceptance_test.go b/internal/daemon/v2_acceptance_test.go index 1a64a6601..b97fde567 100644 --- a/internal/daemon/v2_acceptance_test.go +++ b/internal/daemon/v2_acceptance_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -26,7 +27,7 @@ type v2Fixture struct { func newV2Fixture(t *testing.T, runner Runner, origins ...string) v2Fixture { t.Helper() - paths, err := Paths(t.TempDir()) + paths, err := daemonconn.Paths(t.TempDir()) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/v2_crash_test.go b/internal/daemon/v2_crash_test.go index 61cde37fd..b1e6c6f70 100644 --- a/internal/daemon/v2_crash_test.go +++ b/internal/daemon/v2_crash_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/webgateway" @@ -150,7 +151,7 @@ func appendCrashEffect(home string) error { func serveCrashFixture(t *testing.T, home string, store *session.Store, rootID string, runner Runner) v2Fixture { t.Helper() - paths, err := Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/v2_sdk_test.go b/internal/daemon/v2_sdk_test.go index 3ab27ae8d..9200ae2a4 100644 --- a/internal/daemon/v2_sdk_test.go +++ b/internal/daemon/v2_sdk_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tools" @@ -49,7 +50,7 @@ func TestV2SDKBridge(t *testing.T) { if err != nil { t.Fatal(err) } - paths, err := Paths(filepath.Join(directory, "home")) + paths, err := daemonconn.Paths(filepath.Join(directory, "home")) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/autostart_unix.go b/internal/daemonconn/autostart_unix.go similarity index 99% rename from internal/daemon/autostart_unix.go rename to internal/daemonconn/autostart_unix.go index 552cfafee..b2972331c 100644 --- a/internal/daemon/autostart_unix.go +++ b/internal/daemonconn/autostart_unix.go @@ -1,6 +1,6 @@ //go:build unix -package daemon +package daemonconn import ( "context" diff --git a/internal/daemonconn/autostart_unix_test.go b/internal/daemonconn/autostart_unix_test.go new file mode 100644 index 000000000..7fcd53e21 --- /dev/null +++ b/internal/daemonconn/autostart_unix_test.go @@ -0,0 +1,66 @@ +//go:build unix + +package daemonconn + +import ( + "errors" + "os" + "path/filepath" + "testing" +) + +func TestLaunchDaemonProcessUsesOwnerOnlyLog(t *testing.T) { + paths, err := Paths(t.TempDir()) + if err != nil { + t.Fatal(err) + } + if err := launchDaemonProcess(paths, "/usr/bin/true"); err != nil { + t.Fatal(err) + } + info, err := os.Stat(filepath.Join(paths.Home, "daemon.log")) + if err != nil || info.Mode().Perm() != 0o600 { + t.Fatalf("daemon log mode = %v, %v", info, err) + } +} + +func TestSelfLaunchAndRestartUseCurrentExecutable(t *testing.T) { + previousExecutable, previousReplace := selfExecutable, replaceProcess + selfExecutable = func() (string, error) { return "/usr/bin/true", nil } + var replaced bool + + replaceProcess = func(path string, args, _ []string) error { + replaced = path == "/usr/bin/true" && len(args) == 2 && args[1] == "_daemon" + return errors.New("exec stopped for test") + } + t.Cleanup(func() { selfExecutable, replaceProcess = previousExecutable, previousReplace }) + paths, err := Paths(t.TempDir()) + if err != nil { + t.Fatal(err) + } + if err := LaunchSelfDaemon(paths); err != nil { + t.Fatal(err) + } + if err := RestartSelfDaemon(); err == nil || !replaced { + t.Fatalf("restart replacement = %v, called=%t", err, replaced) + } +} + +func TestSelfLaunchAndRestartReportExecutableFailures(t *testing.T) { + previousExecutable := selfExecutable + want := errors.New("executable unavailable") + selfExecutable = func() (string, error) { return "", want } + t.Cleanup(func() { selfExecutable = previousExecutable }) + paths, err := Paths(t.TempDir()) + if err != nil { + t.Fatal(err) + } + if err := LaunchSelfDaemon(paths); !errors.Is(err, want) { + t.Fatalf("launch executable error = %v", err) + } + if err := RestartSelfDaemon(); !errors.Is(err, want) { + t.Fatalf("restart executable error = %v", err) + } + if err := launchDaemonProcess(paths, filepath.Join(t.TempDir(), "missing")); err == nil { + t.Fatal("missing daemon executable launched") + } +} diff --git a/internal/daemonconn/protocol.go b/internal/daemonconn/protocol.go new file mode 100644 index 000000000..7fd3a6978 --- /dev/null +++ b/internal/daemonconn/protocol.go @@ -0,0 +1,17 @@ +package daemonconn + +import ( + "time" + + "github.com/context-labs/whip/internal/protocol" +) + +const InitializationTimeout = 5 * time.Second + +const MaxOutboundEnvelopes = 1024 + +const MaxContentChunk = 256 << 10 + +type EventNotification struct { + Event protocol.ProtocolEvent `json:"event"` +} diff --git a/internal/daemonconn/socket_unix.go b/internal/daemonconn/socket_unix.go new file mode 100644 index 000000000..621716dcd --- /dev/null +++ b/internal/daemonconn/socket_unix.go @@ -0,0 +1,79 @@ +//go:build unix + +package daemonconn + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + "net" + "os" + "path/filepath" + "syscall" + "time" +) + +const maxUnixSocketPath = 100 + +var ErrDaemonOwned = errors.New("another daemon owns this runtime") + +type RuntimePaths struct { + Home string + Runtime string + Socket string + Lock string +} + +func Paths(home string) (RuntimePaths, error) { + paths, err := ResolvePaths(home) + if err != nil { + return RuntimePaths{}, err + } + for _, dir := range []string{paths.Home, paths.Runtime} { + if err := os.MkdirAll(dir, 0o700); err != nil { + return RuntimePaths{}, err + } + if err := os.Chmod(dir, 0o700); err != nil { //nolint:gosec // directories require execute permission and remain owner-only. + return RuntimePaths{}, err + } + } + return paths, nil +} + +// ResolvePaths computes daemon locations without creating or modifying them. +// Discovery must use this instead of Paths so inspecting a stopped installation +// does not initialize a runtime or change existing directory permissions. +func ResolvePaths(home string) (RuntimePaths, error) { + if home == "" { + return RuntimePaths{}, errors.New("runtime home is required") + } + abs, err := filepath.Abs(filepath.Join(home, "runtime-v2")) + if err != nil { + return RuntimePaths{}, err + } + runtimeDir := abs + socket := filepath.Join(runtimeDir, "daemon.sock") + if len(socket) >= maxUnixSocketPath { + digest := sha256.Sum256([]byte(abs)) + runtimeDir = filepath.Join(os.TempDir(), fmt.Sprintf("whip-%d-%s", os.Getuid(), hex.EncodeToString(digest[:8]))) + socket = filepath.Join(runtimeDir, "daemon.sock") + } + return RuntimePaths{Home: abs, Runtime: runtimeDir, Socket: socket, Lock: filepath.Join(runtimeDir, "daemon.lock")}, nil +} + +func DialLocal(paths RuntimePaths, timeout time.Duration) (net.Conn, error) { + info, err := os.Lstat(paths.Socket) + if err != nil { + return nil, err + } + if info.Mode()&os.ModeSocket == 0 || info.Mode().Perm() != 0o600 { + return nil, errors.New("daemon socket is not owner-only") + } + stat, ok := info.Sys().(*syscall.Stat_t) + if !ok || int(stat.Uid) != os.Getuid() { + return nil, errors.New("daemon socket has a different owner") + } + return (&net.Dialer{Timeout: timeout}).DialContext(context.Background(), "unix", paths.Socket) +} diff --git a/internal/daemonconn/socket_unix_test.go b/internal/daemonconn/socket_unix_test.go new file mode 100644 index 000000000..9d4576b9c --- /dev/null +++ b/internal/daemonconn/socket_unix_test.go @@ -0,0 +1,51 @@ +//go:build unix + +package daemonconn + +import ( + "errors" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestResolvePathsDoesNotCreateRuntime(t *testing.T) { + t.Parallel() + root, err := os.MkdirTemp("/tmp", "whip-paths-") //nolint:usetesting // Exercise both short and hashed Unix socket paths on macOS. + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = os.RemoveAll(root) }) + for _, test := range []struct { + name string + home string + fallback bool + }{ + {name: "short path", home: filepath.Join(root, "home")}, + {name: "long path", home: filepath.Join(root, strings.Repeat("long", 40)), fallback: true}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + paths, err := ResolvePaths(test.home) + if err != nil { + t.Fatal(err) + } + if (paths.Runtime != paths.Home) != test.fallback { + t.Fatalf("runtime fallback = %+v", paths) + } + for _, path := range []string{test.home, paths.Home, paths.Runtime} { + if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("resolving paths touched %s: %v", path, err) + } + } + created, err := Paths(test.home) + if test.fallback { + t.Cleanup(func() { _ = os.RemoveAll(paths.Runtime) }) + } + if err != nil || created != paths { + t.Fatalf("startup and discovery resolved different paths: %+v, %+v, %v", paths, created, err) + } + }) + } +} diff --git a/internal/session/create.go b/internal/session/create.go new file mode 100644 index 000000000..eb57b29be --- /dev/null +++ b/internal/session/create.go @@ -0,0 +1,18 @@ +package session + +type CreateSession struct { + ExecutionEngine string `json:"execution_engine,omitempty"` + // Definition selects the agent definition; empty means the coding agent. + // DefinitionRevision is pinned by the daemon for registered definitions and + // is not accepted from clients. + Definition string `json:"definition,omitempty"` + DefinitionRevision string `json:"definition_revision,omitempty"` + Kind SessionKind `json:"kind"` + CWD string `json:"cwd"` + Model string `json:"model"` + Provider string `json:"provider"` + // Effort is "off" or a catalog level. Blank asks the daemon to resolve the + // definition's default, else the configured default, against the model. + Effort string `json:"effort,omitempty"` + PermissionMode string `json:"permission_mode,omitempty"` +} diff --git a/internal/tui/client.go b/internal/tui/client.go index ed513aa07..d77ce6bdd 100644 --- a/internal/tui/client.go +++ b/internal/tui/client.go @@ -15,9 +15,10 @@ import ( "charm.land/bubbles/v2/spinner" "charm.land/bubbles/v2/textinput" + "github.com/context-labs/whip/internal/daemonconn" + bubbletea "charm.land/bubbletea/v2" "github.com/charmbracelet/colorprofile" - "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" @@ -79,7 +80,7 @@ func Run(cfg *config.Config, modelName, provName, resumeID string, cautious, yol if err != nil { return "", err } - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { return "", err } @@ -90,7 +91,7 @@ func Run(cfg *config.Config, modelName, provName, resumeID string, cautious, yol ProtocolMajor: daemon.ProtocolMajor, BuildID: Version, ClientKind: "tui", ClientID: clientID, Capabilities: []string{"commands", "events", "snapshots", "permissions"}, Cursors: cursors, - }, func() error { return daemon.LaunchSelfDaemon(paths) }) + }, func() error { return daemonconn.LaunchSelfDaemon(paths) }) if err != nil || resumeID == "" || (engine == "" && definition == "") || resumeChecked { return connection, err } diff --git a/internal/tui/client_integration_test.go b/internal/tui/client_integration_test.go index bfcaf3b56..1b0d44168 100644 --- a/internal/tui/client_integration_test.go +++ b/internal/tui/client_integration_test.go @@ -16,6 +16,7 @@ import ( "github.com/context-labs/whip/internal/capability" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -36,7 +37,7 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { if err := cfg.Save(); err != nil { t.Fatal(err) } - paths, err := daemon.Paths(home) + paths, err := daemonconn.Paths(home) if err != nil { t.Fatal(err) } From e289b4ea3344b6fdd45a8782d17c5c66084e90e4 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:35:53 -0700 Subject: [PATCH 47/67] test(tui): align startup title fixture with generation policy --- .github/workflows/ci.yml | 2 + docs/backend-reorganization-plan.md | 54 +++++++++++++++++++++++++ internal/tui/client_integration_test.go | 49 +++++++++++++++++++--- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fb4400a5..65f24f6b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -179,6 +179,8 @@ jobs: run: go test -race ./internal/daemon -run '^(TestRuntimeAcceptance.*|TestRuntimePathsAndOwnerLock|TestOwnerOnlySocketRefusesUnsafeState)$' - name: Shared native connection and command presentation run: go test -race ./internal/daemonconn ./internal/commandpresentation + - name: TUI startup and automatic title over both transports + run: go test -race -tags=integration ./internal/tui -run '^TestInteractiveSessionOverTrustedProtocol$' - name: Compact agent receipts and grant retrieval run: go test -race -tags=integration ./internal/daemon -run '^TestRecursiveAgent(ReceiptsWithLargeMCPGrants|GrantInspectionAccess)$' - name: RLM worker containment diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index e2382af77..a976dd29f 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -680,6 +680,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Workspace ownership (plan PR 6) | `codex/backend-reorg-06-workspace-ownership`, based on PR #311 (`42285977df445ac79334ac96e465d44f057f0350`). | A green, mutation-calibrated composition test precedes the ownership change. Host startup supplies one coordinator to storage; existing root/child/tool borrowers retain the same accessor and implementation. Validation and the deliberate remaining dependency are recorded below. | | Gateway fixture synchronization | `067fe82cd90b99aed42efa80c24e3917ba96e820`, [PR #313](https://github.com/context-labs/whip/pull/313), following workspace ownership. | Eight test-only lines synchronize the two pipelined browser writes before backend rejection. Existing assertions remain exact; the detailed baseline diagnosis and checks are below. | | Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | +| Shared native plumbing (plan PR 7) | `3127d8ef67c3d59cd70f55ad697102e275c2a6fc`, [PR #315](https://github.com/context-labs/whip/pull/315), based on PR #314. | Shared connection primitives and command presentation move without changing client/server policy. The declaration, characterization, full affected-suite and fresh fixed/immediate-base evidence is recorded below. The PR remains unmerged. | +| Tagged TUI title fixture repair | `codex/backend-reorg-07a-tui-title-fixture`, based on PR #315 (`3127d8ef67c3d59cd70f55ad697102e275c2a6fc`). | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1234,3 +1236,55 @@ This pre-commit local run records the characterization SHA plus its complete staged extraction diff. Only the reviewed decoder comment and this ledger were updated afterward; no executable behavior changed. Hosted checks will record the final commit and actual PR parent separately. + +### Tagged TUI title fixture repair before native client extraction + +The existing `TestInteractiveSessionOverTrustedProtocol` failed on both Unix +and WebSocket on clean PR #315, with correct model/provider and two transcript +messages but the prompt-derived title instead of `Worker Investigation`. +The same fixture and policy were present at the fixed development revision +`271c0f8d2a35648d1b45056d57432590b783483c`: the fake's obsolete +`GenerateTitle(context.Context)` signature did not implement the current +prompt-taking optional interface, its 19-character input was below the existing +20-rune generation threshold, and it treated the first, provisional title event +as a generated title. This is baseline fixture drift, not a client extraction +regression. Evidence: `/private/tmp/whip-tui-title-fixture-diagnosis.md` and +`/private/tmp/whip-pr8-parent-native-title.log`. + +The test now supplies an explicit longer prompt and a matching fake that records +the exact generation input. A cancellable test-only channel holds generation +until the client receives the provisional title; the test then requires the +generated title event and the original final model/provider/title/two-message +snapshot assertion. The original 10-second context remains. There are no +sleeps, timeout increases, production changes or altered title-policy defaults. +The existing tagged test command is added to the Linux/macOS runtime matrix; +Taskfile acceptance already runs it, and every prior selector remains. + +Both transports passed all three race repetitions without a PTY (3.634s), +matching the hosted command's environment. The full TUI race/shuffle suite, +including integration-tag tests, passed in a real PTY (10.164s). Existing +`TestTitleLifecycle*`, `TestGenerateTitle*` and `TestProvisionalTitle*` policy +checks passed three race repetitions (daemon 13.417s, session 5.268s). +Four throwaway Go overlays independently restored the old signature or short +prompt, changed the captured input, or returned the wrong generated title; +each failed its intended assertion. The repository was never mutated for +these negative controls. Results are +`/private/tmp/whip-title-fixture-negative-results.json`. + +Module build, vet, whipvet, all-package integration-tag compilation, full +CI-equivalent default-tag golangci-lint 2.13.1, and all 36 workflow-policy tests +passed. Evidence logs use +`/private/tmp/whip-title-fixture-{focused,tui-full,policy,build-vet,lint}.log`. +An additional integration-tag-only TUI lint run found the inherited `noctx` +finding on this fixture's unchanged `net.Listen("unix", paths.Socket)` call. +It did not pass. That call remains unchanged to keep this repair focused; +there is no suppression. Exact output and parent-source comparison are +`/private/tmp/whip-title-fixture-tagged-lint.log` and +`/private/tmp/whip-title-fixture-listener-proof.txt`. This supplemental result +is distinct from the passing required lint gate and tagged compile/tests. +Local runners used disposable homes and removed ambient provider credentials; +no installed daemon or live provider was used. Product code, SDK/protocol, +schema/migrations and dependency files are unchanged from PR #315. Hosted +compatibility and workflow results will record this separate prerequisite's +published head and immediate parent; local checks do not stand in for those +future results. diff --git a/internal/tui/client_integration_test.go b/internal/tui/client_integration_test.go index 1b0d44168..5098dbc64 100644 --- a/internal/tui/client_integration_test.go +++ b/internal/tui/client_integration_test.go @@ -5,6 +5,7 @@ package tui import ( "context" "crypto/rand" + "encoding/json" "net" "os" "path/filepath" @@ -51,8 +52,10 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { t.Cleanup(func() { _ = store.Close() }) processes := capability.NewProcessManager() t.Cleanup(func() { _ = processes.Close() }) + titleRelease := make(chan struct{}) + runner := &startupRunner{titleRelease: titleRelease} owner, err := daemon.New(store, processes, func(context.Context, session.Meta, []llm.Message) (daemon.Components, error) { - return daemon.Components{Runner: &startupRunner{}}, nil + return daemon.Components{Runner: runner}, nil }) if err != nil { t.Fatal(err) @@ -136,11 +139,13 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { if _, ok := m.requestHostSkills()().(clientSkillsMsg); !ok { t.Fatal("startup skill discovery failed") } - _, command := m.submitClientAction("submit", protocol.SubmitPayload{Text: "Investigate workers"}, "") + const prompt = "Investigate workers and their queue" + _, command := m.submitClientAction("submit", protocol.SubmitPayload{Text: prompt}, "") message := clientCommandFrom(t, command) if message.err != nil || message.result.Status != "succeeded" { t.Fatalf("first prompt: %+v", message) } + sawProvisional := false for { select { case update := <-client.Updates(): @@ -150,6 +155,27 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { if update.Event == nil || update.Event.Kind != "session.title.updated" { continue } + var title protocol.SessionUpdateEvent + if err := json.Unmarshal(update.Event.Payload, &title); err != nil { + t.Fatal(err) + } + if title.Title == prompt { + if sawProvisional { + t.Fatal("provisional title delivered twice") + } + sawProvisional = true + close(titleRelease) + continue + } + if !sawProvisional || title.Title != "Worker Investigation" { + t.Fatalf("unexpected title event: %+v (provisional seen: %v)", title, sawProvisional) + } + runner.mu.Lock() + titlePrompt := runner.titlePrompt + runner.mu.Unlock() + if titlePrompt != prompt { + t.Fatalf("title generation prompt = %q, want %q", titlePrompt, prompt) + } snapshot, err := client.Snapshot(ctx) if err != nil { t.Fatal(err) @@ -167,8 +193,10 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { } type startupRunner struct { - mu sync.Mutex - history []llm.Message + mu sync.Mutex + history []llm.Message + titlePrompt string + titleRelease <-chan struct{} } func (r *startupRunner) Turn(_ context.Context, input string, authored bool, started func(), _ func(string)) (string, error) { @@ -189,6 +217,15 @@ func (r *startupRunner) History() []llm.Message { func (*startupRunner) Close() {} -func (*startupRunner) GenerateTitle(context.Context) (string, llm.Usage, error) { - return "Worker Investigation", llm.Usage{}, nil +func (r *startupRunner) GenerateTitle(ctx context.Context, prompt string) (string, llm.Usage, error) { + r.mu.Lock() + r.titlePrompt = prompt + r.mu.Unlock() + // Hold generation until the client has observed the committed provisional title. + select { + case <-r.titleRelease: + return "Worker Investigation", llm.Usage{}, nil + case <-ctx.Done(): + return "", llm.Usage{}, ctx.Err() + } } From ecf96616acf48233658620c81286a08fd9bada80 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:31:12 -0700 Subject: [PATCH 48/67] refactor(backend): separate native Go clients from daemon --- .github/workflows/ci.yml | 2 +- Taskfile.yaml | 4 +- cmd/whip/acp.go | 22 +- cmd/whip/acp_test.go | 12 +- cmd/whip/auth_daemon.go | 26 +- cmd/whip/auth_inferencenet.go | 8 +- cmd/whip/auth_inferencenet_test.go | 12 +- cmd/whip/auth_openai.go | 4 +- cmd/whip/daemon_client.go | 13 +- cmd/whip/daemon_client_test.go | 9 +- cmd/whip/daemon_manage.go | 11 +- cmd/whip/daemon_test.go | 42 +- .../desktop_runtime_sync_integration_test.go | 10 +- cmd/whip/gateway_process.go | 4 +- cmd/whip/main_test.go | 11 +- cmd/whip/mcp.go | 8 +- cmd/whip/run.go | 22 +- cmd/whip/run_output_test.go | 12 +- cmd/whip/sessions.go | 4 +- cmd/whip/sessions_export.go | 6 +- cmd/whip/sessions_export_test.go | 8 +- cmd/whip/update.go | 11 +- cmd/whip/web.go | 10 +- cmd/whip/web_test.go | 5 +- docs/architecture.md | 1 + docs/backend-reorganization-plan.md | 81 ++- docs/features.md | 8 +- internal/acp/bridge.go | 25 +- internal/acp/bridge_test.go | 81 +-- internal/acp/session_cleanup_test.go | 8 +- internal/{daemon => client}/autostart.go | 11 +- internal/client/autostart_test.go | 31 + internal/{daemon => client}/client.go | 97 +-- internal/client/collection.go | 26 + internal/client/command_outcome.go | 13 + internal/client/command_outcome_test.go | 29 + internal/client/completion_client.go | 19 + internal/{daemon => client}/content_client.go | 10 +- internal/{daemon => client}/history_client.go | 6 +- internal/client/invoke.go | 13 + internal/client/protocol_edge_test.go | 290 ++++++++ .../{daemon => client}/provider_client.go | 26 +- internal/client/query.go | 24 + .../root_cancel_target_test.go | 14 +- internal/{daemon => client}/root_client.go | 83 +-- .../root_client_services_behavior_test.go | 70 ++ internal/client/root_client_test.go | 661 ++++++++++++++++++ internal/client/subscription.go | 45 ++ .../client/subscription_lifecycle_test.go | 39 ++ internal/client/transport_test.go | 16 + internal/client/view.go | 28 + .../{daemon => client}/websocket_client.go | 5 +- internal/daemon/acceptance_test.go | 5 +- internal/daemon/architecture_test.go | 28 +- internal/daemon/autostart_test.go | 26 +- internal/daemon/collection.go | 18 - internal/daemon/command_outcome.go | 8 - internal/daemon/command_outcome_test.go | 25 - internal/daemon/completion_client.go | 15 - internal/daemon/gateway_ownership_test.go | 5 +- internal/daemon/gateway_test.go | 3 +- internal/daemon/identity_test.go | 5 +- internal/daemon/invoke.go | 6 - internal/daemon/mcp_import_service_test.go | 3 +- internal/daemon/protocol_edge_test.go | 271 ------- .../daemon/provider_client_behavior_test.go | 46 +- .../provider_client_configuration_test.go | 4 +- internal/daemon/provider_connections_test.go | 4 +- internal/daemon/provider_integration_test.go | 5 +- internal/daemon/provider_rpc.go | 6 +- internal/daemon/provider_selection_test.go | 3 +- internal/daemon/query.go | 16 - internal/daemon/restart_test.go | 5 +- .../root_client_services_behavior_test.go | 60 -- internal/daemon/root_client_test.go | 651 +---------------- internal/daemon/runtime_parity_test.go | 5 +- internal/daemon/server_gateway_test.go | 5 +- internal/daemon/server_test.go | 19 +- internal/daemon/session_summaries_test.go | 3 +- .../daemon/skill_catalog_completion_test.go | 3 +- internal/daemon/subscription.go | 38 - .../daemon/subscription_lifecycle_test.go | 33 - internal/daemon/v2_acceptance_test.go | 13 +- internal/daemon/v2_crash_test.go | 11 +- internal/daemon/v2_latency_test.go | 4 +- internal/daemon/v2_sdk_test.go | 3 +- internal/daemon/view.go | 20 - internal/tui/client.go | 64 +- internal/tui/client_completion.go | 9 +- internal/tui/client_completion_test.go | 3 +- internal/tui/client_export.go | 7 +- internal/tui/client_export_test.go | 3 +- internal/tui/client_history.go | 5 +- internal/tui/client_history_test.go | 8 +- internal/tui/client_integration_test.go | 13 +- internal/tui/client_queue_test.go | 26 +- internal/tui/client_test.go | 127 ++-- internal/tui/daemon_views.go | 12 +- internal/tui/hit_test.go | 8 +- internal/tui/mcp_palette_test.go | 4 +- internal/tui/menu_key_test.go | 6 +- internal/tui/model_accounting_test.go | 6 +- internal/tui/opencode_client_test.go | 6 +- internal/tui/paste_chip_test.go | 8 +- internal/tui/question_test.go | 19 +- internal/tui/repl_panel.go | 11 +- internal/tui/repl_panel_test.go | 66 +- internal/tui/setup.go | 21 +- internal/tui/setup_default_test.go | 3 +- internal/tui/setup_host.go | 21 +- internal/tui/setup_provider.go | 6 +- internal/tui/setup_provider_test.go | 10 +- internal/tui/setup_test.go | 38 +- internal/tui/startup_test.go | 22 +- internal/tui/thin_update.go | 12 +- internal/tui/tui.go | 8 +- 116 files changed, 2120 insertions(+), 1843 deletions(-) rename internal/{daemon => client}/autostart.go (72%) create mode 100644 internal/client/autostart_test.go rename internal/{daemon => client}/client.go (72%) create mode 100644 internal/client/collection.go create mode 100644 internal/client/command_outcome.go create mode 100644 internal/client/command_outcome_test.go create mode 100644 internal/client/completion_client.go rename internal/{daemon => client}/content_client.go (81%) rename internal/{daemon => client}/history_client.go (77%) create mode 100644 internal/client/invoke.go create mode 100644 internal/client/protocol_edge_test.go rename internal/{daemon => client}/provider_client.go (90%) create mode 100644 internal/client/query.go rename internal/{daemon => client}/root_cancel_target_test.go (83%) rename internal/{daemon => client}/root_client.go (85%) create mode 100644 internal/client/root_client_services_behavior_test.go create mode 100644 internal/client/root_client_test.go create mode 100644 internal/client/subscription.go create mode 100644 internal/client/subscription_lifecycle_test.go create mode 100644 internal/client/transport_test.go create mode 100644 internal/client/view.go rename internal/{daemon => client}/websocket_client.go (84%) delete mode 100644 internal/daemon/command_outcome_test.go delete mode 100644 internal/daemon/completion_client.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65f24f6b0..e309f212b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -178,7 +178,7 @@ jobs: - name: Daemon lifecycle and socket ownership run: go test -race ./internal/daemon -run '^(TestRuntimeAcceptance.*|TestRuntimePathsAndOwnerLock|TestOwnerOnlySocketRefusesUnsafeState)$' - name: Shared native connection and command presentation - run: go test -race ./internal/daemonconn ./internal/commandpresentation + run: go test -race ./internal/daemonconn ./internal/commandpresentation ./internal/client - name: TUI startup and automatic title over both transports run: go test -race -tags=integration ./internal/tui -run '^TestInteractiveSessionOverTrustedProtocol$' - name: Compact agent receipts and grant retrieval diff --git a/Taskfile.yaml b/Taskfile.yaml index 3815ffd7a..f1af26f2f 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -102,13 +102,13 @@ tasks: acceptance: desc: "Run the deterministic daemon, recursive-agent, client, and RLM release acceptance suite" cmds: - - go test -race ./internal/daemonconn ./internal/commandpresentation + - go test -race ./internal/daemonconn ./internal/commandpresentation ./internal/client - go test -race -tags=integration ./internal/tui -run '^TestInteractiveSessionOverTrustedProtocol$' - go test -race -tags=integration ./internal/daemon -run '^TestRecursiveAgent(ReceiptsWithLargeMCPGrants|GrantInspectionAccess)$' - go test -race ./internal/daemon ./internal/session ./internal/protocol -run '^(TestV2|TestV3|TestTrustedClient|TestRuntimeRegistry|TestCommandAcceptance|TestClientAcceptance|TestDeleteAcceptance|TestQuestionSnapshot|TestRootCollection|TestSessionCatalog|TestIncompatible|TestVersionFive|TestVersionSix|TestBounded|TestTranscriptPage)' - go test -race ./internal/mcp ./internal/tools ./internal/session ./internal/daemon ./internal/acp ./internal/tui -run '^(TestMCP|TestExternalPermission|TestCheckedManager|TestConfigTrust|TestConfigDiscoveryReportsWinningProvenance|TestManagerOwnsConfigMapsAndNeverTrustsSourceLabels|TestCapabilityFinishStorageFailureSettlesAndReleasesCapacity|TestCapabilityFinishDeniedSettlesAdmittedOperation|TestBridgeMCP)' - go test -race ./internal/daemon -run '^(TestRuntimeAcceptance.*|TestRuntimePathsAndOwnerLock|TestOwnerOnlySocketRefusesUnsafeState|TestArchitecture.*|TestRecursiveRuntimeUsesOneInterfaceAtEveryDepth|TestRecursiveSpawnQueuesUnderWorkerPressure|TestRecursiveChildrenInheritOrExplicitlyOverrideOneAgentConfiguration|TestRecursiveAgentClientControlsAuthorizeAndPersist|TestRecursiveRuntimeRestoresRetainedAgentAndTranscript|TestQueuedInitialAgentPromptSurvivesRestartExactlyOnce|TestConcurrentChildTurnPressureKeepsPromptQueued|TestSuspendedKernelNoticeIsEphemeral|TestSuspendedKernelRestoresScratchWithEphemeralNotice|TestBackgroundShellJobOutlivesTheCellAndTurn|TestToolHostRunsOnlyRestrictedToolCommands|TestPermissionRuleResolvesCoveredPromptsAndSkipsFutureOnes|TestUserAskRoundTripsThroughQuestionEvents|TestUserAskDismissAndCancelClose|TestUserAskIsRootOnlyAndValidatesArguments)$' - - go test -race ./internal/session ./internal/capability ./internal/daemon -run '^(TestRuntimeTransitionIsAtomicAndLargeValuesAreHandleBacked|TestStatePrivateIsolationBlackboardVisibilityAndHandles|TestMailboxMessageIsCanonicalAndBodyStaysBehindRead|TestMailboxTurnDeliversOnCommitAndNewMailStaysPending|TestFailedMailboxTurnRedeliversPendingMail|TestRootMailboxFailureRequiresExplicitInputAcrossRestart|TestRootTurnLifecycleIdentifiesExactTurn|TestMessageDeliveryClassesAndDeferral|TestAgentAdmissionPersistsPromptAtomically|TestRecoveryKeepsQueuedAgentPromptButInterruptsRunningInput|TestChildBudgetClampingDepthAndActiveChildLimits|TestBudgetKindsExhaustIndependently|TestCapabilityPermissionSurvivesDispatcherAndRevalidates|TestDispatcherRunsDirectAndPersistedPermissionThroughOnePath|TestDispatcherRejectsCanonicalPathChangeAfterApproval|TestDispatcherWorkspaceMutationRunsAlongsidePathMutations|TestRecoveryInterruptsEveryNonterminalRuntimeRecord|TestSlowOutboundClientClosesWithoutStoppingDaemon|TestRootsRunConcurrentlyAndCallerCancellationDoesNotOwnWork|TestMCPLifecyclePanicFailsOnlyItsRoot|TestRootClientReconnectsStableCommandWithoutDuplicateEvent|TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution)$' + - go test -race ./internal/session ./internal/capability ./internal/daemon ./internal/client -run '^(TestRuntimeTransitionIsAtomicAndLargeValuesAreHandleBacked|TestStatePrivateIsolationBlackboardVisibilityAndHandles|TestMailboxMessageIsCanonicalAndBodyStaysBehindRead|TestMailboxTurnDeliversOnCommitAndNewMailStaysPending|TestFailedMailboxTurnRedeliversPendingMail|TestRootMailboxFailureRequiresExplicitInputAcrossRestart|TestRootTurnLifecycleIdentifiesExactTurn|TestMessageDeliveryClassesAndDeferral|TestAgentAdmissionPersistsPromptAtomically|TestRecoveryKeepsQueuedAgentPromptButInterruptsRunningInput|TestChildBudgetClampingDepthAndActiveChildLimits|TestBudgetKindsExhaustIndependently|TestCapabilityPermissionSurvivesDispatcherAndRevalidates|TestDispatcherRunsDirectAndPersistedPermissionThroughOnePath|TestDispatcherRejectsCanonicalPathChangeAfterApproval|TestDispatcherWorkspaceMutationRunsAlongsidePathMutations|TestRecoveryInterruptsEveryNonterminalRuntimeRecord|TestSlowOutboundClientClosesWithoutStoppingDaemon|TestRootsRunConcurrentlyAndCallerCancellationDoesNotOwnWork|TestMCPLifecyclePanicFailsOnlyItsRoot|TestRootClientReconnectsStableCommandWithoutDuplicateEvent|TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution)$' - go test -race ./internal/tui ./internal/acp ./cmd/whip -run '^(TestClientReconnectReplayAndSnapshotFallback|TestClientReattachesInFlightActionWithSameIdentityAfterDisconnect|TestDaemonBackedModelRendersWithoutAnAgent|TestThinPaletteAndAgentControlsStayDaemonBacked|TestBridgeDaemonCutoverMapsEventsAndContent|TestBridgePermissionAndModesWithoutCredentials|TestBridgeQuestionMapsToPermissionPromptAndAnswerOp|TestBridgeConcurrentSessionsAndCloseDetach|TestRunDaemonAlwaysUsesRLMRuntime|TestRunTextOutput|TestSessionsCLI|TestMCPServeStopsCleanlyOnStdinEOF|TestMCPTestCLIReady|TestACPDaemonBackendAndMCPToolsRoundTrip)$' - go test -race ./internal/rlm -run '^(TestKernelEnforcesStepWallOutputHostAndFrameLimits|TestKernelDeadlineReapsProcessGroup|TestKernelDeniesAmbientAuthority|TestKernelStripsDaemonEnvironment|TestKernelReservationAndCrashRestart|TestKernelManagerSchedulesFIFOWithoutEvictingRunningTurns|TestKernelManagerEvictsIdleWorkersInLRUOrderAcrossRetainedSessions|TestKernelManagerRemovesCancelledWaitersAndWakesOnShutdown|TestKernelTurnLeasePreservesScratchAndSuspendRejectsRunning|TestKernelScratchSurvivesSuspensionAndMidTurnRestart)$' - go test -race ./evals/rlm -run '^TestDeterministicRLMEvaluationReport$' diff --git a/cmd/whip/acp.go b/cmd/whip/acp.go index f14941960..fc59e84a5 100644 --- a/cmd/whip/acp.go +++ b/cmd/whip/acp.go @@ -14,15 +14,15 @@ import ( "os/signal" "syscall" - acpsdk "github.com/coder/acp-go-sdk" + daemonclient "github.com/context-labs/whip/internal/client" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" + acpsdk "github.com/coder/acp-go-sdk" "github.com/context-labs/whip/internal/acp" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/openaiauth" - "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/session" ) func acpCLI(args []string) error { @@ -95,23 +95,23 @@ type acpDaemonBackend struct { provider string } -func (b *acpDaemonBackend) NewRoot(ctx context.Context, cwd string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *acpDaemonBackend) NewRoot(ctx context.Context, cwd string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { return b.root(ctx, "", cwd, servers) } -func (b *acpDaemonBackend) LoadRoot(ctx context.Context, rootID, _ string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *acpDaemonBackend) LoadRoot(ctx context.Context, rootID, _ string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { return b.root(ctx, rootID, "", servers) } -func (b *acpDaemonBackend) root(ctx context.Context, rootID, cwd string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { - options := daemon.RootClientOptions{ +func (b *acpDaemonBackend) root(ctx context.Context, rootID, cwd string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { + options := daemonclient.RootClientOptions{ ClientID: b.clientID, RootID: rootID, Connector: daemonConnector("acp", b.clientID), } if rootID == "" { - options.Create = &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: cwd, Model: b.model, Provider: b.provider} + options.Create = &session.CreateSession{Kind: session.SessionKindAgent, CWD: cwd, Model: b.model, Provider: b.provider} } - client, err := daemon.NewRootClient(options) + client, err := daemonclient.NewRootClient(options) if err != nil { return nil, err } @@ -149,7 +149,7 @@ func (b *acpDaemonBackend) ListSessions(ctx context.Context, limit int) ([]sessi if err != nil { return nil, err } - result, err := connection.Command(ctx, daemon.CommandParams{ + result, err := connection.Command(ctx, protocol.CommandParams{ CommandID: daemonCommandID(b.clientID, "list"), Scope: string(session.CommandScopeDaemon), Operation: "session.list", Payload: payload, }) diff --git a/cmd/whip/acp_test.go b/cmd/whip/acp_test.go index 590ef65ee..b9bb47774 100644 --- a/cmd/whip/acp_test.go +++ b/cmd/whip/acp_test.go @@ -1,9 +1,5 @@ package main -// Coverage for the ACP CLI's pure helpers: vision resolution (catalog wins, -// config falls back) and whip's base MCP merge. The acpCLI entry point itself -// serves stdio and isn't unit-testable; its helpers are. - import ( "context" "encoding/json" @@ -15,11 +11,15 @@ import ( "time" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" + "github.com/context-labs/whip/internal/protocol" ) +// Coverage for the ACP CLI's pure helpers: vision resolution (catalog wins, +// config falls back) and whip's base MCP merge. The acpCLI entry point itself +// serves stdio and isn't unit-testable; its helpers are. + // acpCLI's config prologue runs before the serve loop: a broken config, an // unknown model, or a provider with no key all error out instead of serving. // These cover the entry point's front half without blocking on stdio. @@ -188,7 +188,7 @@ func TestACPDaemonBackendAndMCPToolsRoundTrip(t *testing.T) { defer func() { _ = root.Close() }() // Exercise the content-parts path used by image-capable ACP clients. - action, err := root.NewAction("submit", daemon.SubmitPayload{ + action, err := root.NewAction("submit", protocol.SubmitPayload{ Text: "remember this", Parts: []llm.ContentPart{{Type: "text", Text: "remember this"}}, }) diff --git a/cmd/whip/auth_daemon.go b/cmd/whip/auth_daemon.go index f64aa096a..fe729ca87 100644 --- a/cmd/whip/auth_daemon.go +++ b/cmd/whip/auth_daemon.go @@ -4,21 +4,21 @@ import ( "context" "errors" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" ) type providerDaemon interface { - ReadConfiguration(context.Context) (daemon.RuntimeConfiguration, error) - SetProviderKey(context.Context, daemon.ProviderKeySetup) (daemon.RuntimeConfiguration, error) - BeginLogin(context.Context) (daemon.ProviderLoginStatus, error) - BeginProviderLogin(context.Context, string) (daemon.ProviderLoginStatus, error) - LoginStatus(context.Context, string) (daemon.ProviderLoginStatus, error) - SelectLoginTeam(context.Context, string, string) (daemon.ProviderLoginStatus, error) - SelectLoginProject(context.Context, string, string) (daemon.ProviderLoginStatus, error) - CreateLoginProject(context.Context, string, string) (daemon.ProviderLoginStatus, error) - ProviderStatus(context.Context, string) (daemon.ProviderStatus, error) - LogoutProvider(context.Context, string) (daemon.ProviderStatus, error) - RotateProviderKey(context.Context, string) (daemon.ProviderStatus, error) + ReadConfiguration(context.Context) (protocol.RuntimeConfiguration, error) + SetProviderKey(context.Context, protocol.ProviderKeySetup) (protocol.RuntimeConfiguration, error) + BeginLogin(context.Context) (protocol.ProviderLoginStatus, error) + BeginProviderLogin(context.Context, string) (protocol.ProviderLoginStatus, error) + LoginStatus(context.Context, string) (protocol.ProviderLoginStatus, error) + SelectLoginTeam(context.Context, string, string) (protocol.ProviderLoginStatus, error) + SelectLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) + CreateLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) + ProviderStatus(context.Context, string) (protocol.ProviderStatus, error) + LogoutProvider(context.Context, string) (protocol.ProviderStatus, error) + RotateProviderKey(context.Context, string) (protocol.ProviderStatus, error) Close() error } @@ -45,6 +45,6 @@ func setupProviderCLI(ctx context.Context, provider, key string, environment boo if err != nil { return err } - _, err = client.SetProviderKey(ctx, daemon.ProviderKeySetup{Revision: current.Revision, Provider: provider, Key: key, Environment: environment}) + _, err = client.SetProviderKey(ctx, protocol.ProviderKeySetup{Revision: current.Revision, Provider: provider, Key: key, Environment: environment}) return err } diff --git a/cmd/whip/auth_inferencenet.go b/cmd/whip/auth_inferencenet.go index a02025739..d4ab3edac 100644 --- a/cmd/whip/auth_inferencenet.go +++ b/cmd/whip/auth_inferencenet.go @@ -14,7 +14,7 @@ import ( "time" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" ) // authInferenceNetCLI implements `whipcode auth inference-net …`: first-class @@ -121,7 +121,7 @@ func providerDeviceLogin(provider string, lifetime time.Duration) error { } status, err = client.SelectLoginTeam(ctx, status.FlowID, id) case "choose_project": - choices := append(append([]daemon.ProviderChoice{}, status.Projects...), daemon.ProviderChoice{ID: "", Name: "+ Create new project"}) + choices := append(append([]protocol.ProviderChoice{}, status.Projects...), protocol.ProviderChoice{ID: "", Name: "+ Create new project"}) id, chooseErr := chooseProviderID("project", choices) if chooseErr != nil { return chooseErr @@ -162,7 +162,7 @@ func providerDeviceLogin(provider string, lifetime time.Duration) error { } } -func chooseProviderID(kind string, choices []daemon.ProviderChoice) (string, error) { +func chooseProviderID(kind string, choices []protocol.ProviderChoice) (string, error) { if len(choices) == 0 { return "", errors.New("provider returned no choices") } @@ -240,7 +240,7 @@ func providerAccountCLI(operation string) error { return err } defer func() { _ = client.Close() }() - var status daemon.ProviderStatus + var status protocol.ProviderStatus switch operation { case "status": status, err = client.ProviderStatus(ctx, config.InferenceNetProvider) diff --git a/cmd/whip/auth_inferencenet_test.go b/cmd/whip/auth_inferencenet_test.go index 67efe6490..5e53e5c52 100644 --- a/cmd/whip/auth_inferencenet_test.go +++ b/cmd/whip/auth_inferencenet_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/inferencenet" + "github.com/context-labs/whip/internal/protocol" ) func TestAuthInferenceNetDispatch(t *testing.T) { @@ -173,14 +173,14 @@ func TestCLIChooser(t *testing.T) { func TestProviderChoiceUsesStableIDsWithDuplicateNames(t *testing.T) { for _, test := range []struct { name, input, want string - choices []daemon.ProviderChoice + choices []protocol.ProviderChoice wantErr bool }{ {name: "no workspaces", wantErr: true}, - {name: "one workspace", choices: []daemon.ProviderChoice{{ID: "team-1", Name: "Work"}}, want: "team-1"}, - {name: "duplicate names", input: "2\n", choices: []daemon.ProviderChoice{{ID: "team-1", Name: "Work"}, {ID: "team-2", Name: "Work"}}, want: "team-2"}, - {name: "new project", input: "2\n", choices: []daemon.ProviderChoice{{ID: "project-1", Name: "Existing"}, {Name: "+ Create new project"}}}, - {name: "invalid choice", input: "3\n", choices: []daemon.ProviderChoice{{ID: "team-1"}, {ID: "team-2"}}, wantErr: true}, + {name: "one workspace", choices: []protocol.ProviderChoice{{ID: "team-1", Name: "Work"}}, want: "team-1"}, + {name: "duplicate names", input: "2\n", choices: []protocol.ProviderChoice{{ID: "team-1", Name: "Work"}, {ID: "team-2", Name: "Work"}}, want: "team-2"}, + {name: "new project", input: "2\n", choices: []protocol.ProviderChoice{{ID: "project-1", Name: "Existing"}, {Name: "+ Create new project"}}}, + {name: "invalid choice", input: "3\n", choices: []protocol.ProviderChoice{{ID: "team-1"}, {ID: "team-2"}}, wantErr: true}, } { t.Run(test.name, func(t *testing.T) { reader, writer, err := os.Pipe() diff --git a/cmd/whip/auth_openai.go b/cmd/whip/auth_openai.go index 71b4c3ec1..20b076b77 100644 --- a/cmd/whip/auth_openai.go +++ b/cmd/whip/auth_openai.go @@ -7,8 +7,8 @@ import ( "os" "time" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/openaiauth" + "github.com/context-labs/whip/internal/protocol" ) func authOpenAICLI(args []string) error { @@ -29,7 +29,7 @@ func authOpenAICLI(args []string) error { return err } defer func() { _ = client.Close() }() - var status daemon.ProviderStatus + var status protocol.ProviderStatus if operation == "logout" { status, err = client.LogoutProvider(ctx, openaiauth.Provider) } else { diff --git a/cmd/whip/daemon_client.go b/cmd/whip/daemon_client.go index 5c116fd14..0265b9a3a 100644 --- a/cmd/whip/daemon_client.go +++ b/cmd/whip/daemon_client.go @@ -8,12 +8,13 @@ import ( "sync/atomic" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" ) -var connectDaemon = func(ctx context.Context, clientKind, clientID string, cursors map[string]int64) (daemon.RootConnection, error) { +var connectDaemon = func(ctx context.Context, clientKind, clientID string, cursors map[string]int64) (daemonclient.RootConnection, error) { dir, err := config.Dir() if err != nil { return nil, err @@ -22,8 +23,8 @@ var connectDaemon = func(ctx context.Context, clientKind, clientID string, curso if err != nil { return nil, err } - return daemon.EnsureClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, + return daemonclient.EnsureClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientKind: clientKind, ClientID: clientID, @@ -32,8 +33,8 @@ var connectDaemon = func(ctx context.Context, clientKind, clientID string, curso }, func() error { return daemonconn.LaunchSelfDaemon(paths) }) } -func daemonConnector(clientKind, clientID string) daemon.RootConnector { - return func(ctx context.Context, cursors map[string]int64) (daemon.RootConnection, error) { +func daemonConnector(clientKind, clientID string) daemonclient.RootConnector { + return func(ctx context.Context, cursors map[string]int64) (daemonclient.RootConnection, error) { return connectDaemon(ctx, clientKind, clientID, cursors) } } diff --git a/cmd/whip/daemon_client_test.go b/cmd/whip/daemon_client_test.go index b55002d93..1f79db6db 100644 --- a/cmd/whip/daemon_client_test.go +++ b/cmd/whip/daemon_client_test.go @@ -9,9 +9,10 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -39,7 +40,7 @@ func useTestDaemon(t *testing.T) { finished := make(chan error, 1) var once sync.Once started := false - connectDaemon = func(callCtx context.Context, clientKind, clientID string, cursors map[string]int64) (daemon.RootConnection, error) { + connectDaemon = func(callCtx context.Context, clientKind, clientID string, cursors map[string]int64) (daemonclient.RootConnection, error) { dir, err := config.Dir() if err != nil { return nil, err @@ -48,8 +49,8 @@ func useTestDaemon(t *testing.T) { if err != nil { return nil, err } - return daemon.EnsureClient(callCtx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: version, ClientKind: clientKind, + return daemonclient.EnsureClient(callCtx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientKind: clientKind, ClientID: clientID, Capabilities: []string{"commands", "events", "snapshots"}, Cursors: cursors, }, func() error { once.Do(func() { diff --git a/cmd/whip/daemon_manage.go b/cmd/whip/daemon_manage.go index 529e0bbc3..d01b736a5 100644 --- a/cmd/whip/daemon_manage.go +++ b/cmd/whip/daemon_manage.go @@ -14,6 +14,7 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" @@ -252,7 +253,7 @@ func daemonLogsCLI(args []string) error { return tailDaemonLog(path, *lines, *follow) } -func probeDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) (daemonStatus, *daemon.Client) { +func probeDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) (daemonStatus, *daemonclient.Client) { status := daemonStatus{ State: "stopped", ClientBuild: version, Socket: paths.Socket, Gateway: protocol.GatewayStatus{State: "stopped"}, GatewayLog: filepath.Join(paths.Home, "web.log"), @@ -260,8 +261,8 @@ func probeDaemon(paths daemonconn.RuntimePaths, timeout time.Duration) (daemonSt } ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - client, err := daemon.DialClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: version, + client, err := daemonclient.DialClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientID: daemonClientID("daemon-status"), ClientKind: "automation", }) if err != nil { @@ -358,7 +359,7 @@ func stopManagedDaemon(paths daemonconn.RuntimePaths, timeout time.Duration, for payload, _ := json.Marshal(map[string]string{"reason": "daemon command"}) ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - result, err := client.Command(ctx, daemon.CommandParams{ + result, err := client.Command(ctx, protocol.CommandParams{ CommandID: daemonCommandID(daemonClientID("daemon-stop"), "checkpoint"), Scope: string(session.CommandScopeDaemon), Operation: "daemon.checkpoint", Payload: payload, }) @@ -368,7 +369,7 @@ func stopManagedDaemon(paths daemonconn.RuntimePaths, timeout time.Duration, for err = fmt.Errorf("daemon checkpoint is %s", result.Status) } } - var notice daemon.RestartNotice + var notice protocol.RestartNotice if err == nil { err = json.Unmarshal([]byte(result.Output), ¬ice) } diff --git a/cmd/whip/daemon_test.go b/cmd/whip/daemon_test.go index 411148d97..3bcd7a4cd 100644 --- a/cmd/whip/daemon_test.go +++ b/cmd/whip/daemon_test.go @@ -20,10 +20,12 @@ import ( "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/agentdef" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/rlm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/webgateway" @@ -66,11 +68,11 @@ func TestRunDaemonPublishesProtocolAndStopsCleanly(t *testing.T) { if err != nil { t.Fatal(err) } - var client *daemon.Client + var client *daemonclient.Client deadline := time.Now().Add(5 * time.Second) for time.Now().Before(deadline) { - client, err = daemon.DialClient(context.Background(), paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: version, ClientID: "daemon-test", ClientKind: "test", + client, err = daemonclient.DialClient(context.Background(), paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientID: "daemon-test", ClientKind: "test", }) if err == nil { break @@ -127,7 +129,7 @@ func TestRunDaemonPublishesProtocolAndStopsCleanly(t *testing.T) { }) } badModel, _ := json.Marshal(map[string]string{"kind": string(session.SessionKindAgent), "cwd": home, "model": "missing", "provider": "inference-net"}) - badCreated, err := client.Command(context.Background(), daemon.CommandParams{ + badCreated, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "bad-model", Scope: "daemon", Operation: "session.create", Payload: badModel, }) if err != nil { @@ -139,7 +141,7 @@ func TestRunDaemonPublishesProtocolAndStopsCleanly(t *testing.T) { payload, _ := json.Marshal(map[string]string{ "kind": string(session.SessionKindAgent), "cwd": home, "model": "kimi-k3-fast", "provider": "inference-net", }) - created, err := client.Command(context.Background(), daemon.CommandParams{ + created, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "create", Scope: "daemon", Operation: "session.create", Payload: payload, }) if err != nil || created.Output == "" || created.Status != "succeeded" { @@ -224,11 +226,11 @@ func TestRunDaemonAlwaysUsesRLMRuntime(t *testing.T) { if err != nil { t.Fatal(err) } - var client *daemon.Client + var client *daemonclient.Client deadline := time.Now().Add(5 * time.Second) for time.Now().Before(deadline) { - client, err = daemon.DialClient(context.Background(), paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: version, ClientID: "rlm-only", ClientKind: "test", + client, err = daemonclient.DialClient(context.Background(), paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientID: "rlm-only", ClientKind: "test", }) if err == nil { break @@ -250,14 +252,14 @@ func TestRunDaemonAlwaysUsesRLMRuntime(t *testing.T) { t.Fatalf("daemon did not become ready: %v", err) } createPayload, _ := json.Marshal(map[string]string{"kind": string(session.SessionKindAgent), "cwd": home, "model": "test-model", "provider": "test-provider"}) - created, err := client.Command(context.Background(), daemon.CommandParams{ + created, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "rlm-create", Scope: "daemon", Operation: "session.create", Payload: createPayload, }) if err != nil { t.Fatal(err) } turnPayload, _ := json.Marshal(map[string]string{"text": "try the runtime"}) - turn, err := client.Command(context.Background(), daemon.CommandParams{ + turn, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "rlm-turn", Scope: "root", RootID: created.Output, Operation: "submit", Payload: turnPayload, }) if err != nil || turn.Output != "rlm done" || calls.Load() != 2 { @@ -526,11 +528,11 @@ func TestRunDaemonCompletesCheckpointRestartHandoff(t *testing.T) { t.Cleanup(func() { restartDaemonBinary = previousRestart }) done := make(chan error, 1) go func() { done <- runDaemon(context.Background(), nil) }() - var client *daemon.Client + var client *daemonclient.Client deadline := time.Now().Add(5 * time.Second) for time.Now().Before(deadline) { - client, err = daemon.DialClient(context.Background(), paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, ClientID: "restart-test", ClientKind: "automation", + client, err = daemonclient.DialClient(context.Background(), paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, ClientID: "restart-test", ClientKind: "automation", }) if err == nil { break @@ -541,13 +543,13 @@ func TestRunDaemonCompletesCheckpointRestartHandoff(t *testing.T) { t.Fatal(err) } payload, _ := json.Marshal(map[string]string{"reason": "test"}) - result, err := client.Command(context.Background(), daemon.CommandParams{ + result, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "checkpoint", Scope: "daemon", Operation: "daemon.checkpoint", Payload: payload, }) if err != nil { t.Fatal(err) } - var notice daemon.RestartNotice + var notice protocol.RestartNotice if err := json.Unmarshal([]byte(result.Output), ¬ice); err != nil { t.Fatal(err) } @@ -568,11 +570,11 @@ func TestRunDaemonCompletesCheckpointStop(t *testing.T) { } done := make(chan error, 1) go func() { done <- runDaemon(context.Background(), nil) }() - var client *daemon.Client + var client *daemonclient.Client deadline := time.Now().Add(5 * time.Second) for time.Now().Before(deadline) { - client, err = daemon.DialClient(context.Background(), paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, ClientID: "stop-test", ClientKind: "automation", + client, err = daemonclient.DialClient(context.Background(), paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, ClientID: "stop-test", ClientKind: "automation", }) if err == nil { break @@ -583,13 +585,13 @@ func TestRunDaemonCompletesCheckpointStop(t *testing.T) { t.Fatal(err) } payload, _ := json.Marshal(map[string]string{"reason": "test"}) - result, err := client.Command(context.Background(), daemon.CommandParams{ + result, err := client.Command(context.Background(), protocol.CommandParams{ CommandID: "checkpoint-stop", Scope: "daemon", Operation: "daemon.checkpoint", Payload: payload, }) if err != nil { t.Fatal(err) } - var notice daemon.RestartNotice + var notice protocol.RestartNotice if err := json.Unmarshal([]byte(result.Output), ¬ice); err != nil { t.Fatal(err) } diff --git a/cmd/whip/desktop_runtime_sync_integration_test.go b/cmd/whip/desktop_runtime_sync_integration_test.go index 806cc70d1..336d2bec1 100644 --- a/cmd/whip/desktop_runtime_sync_integration_test.go +++ b/cmd/whip/desktop_runtime_sync_integration_test.go @@ -14,9 +14,11 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -94,12 +96,12 @@ func TestDesktopCompiledUpdate(t *testing.T) { t.Fatal(err) } run(canonical, "daemon", "start") - connect := func(build string) *daemon.Client { + connect := func(build string) *daemonclient.Client { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) defer cancel() - client, err := daemon.DialClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: build, ClientID: "update-smoke", ClientKind: "test", + client, err := daemonclient.DialClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: build, ClientID: "update-smoke", ClientKind: "test", }) if err != nil { t.Fatal(err) @@ -108,7 +110,7 @@ func TestDesktopCompiledUpdate(t *testing.T) { } client := connect("1.0.0-beta.1") payload, _ := json.Marshal(map[string]string{"kind": "agent", "cwd": directory, "model": "kimi-k3-fast", "provider": "inference-net"}) - created, err := client.Command(t.Context(), daemon.CommandParams{CommandID: "update-smoke-create", Scope: "daemon", Operation: "session.create", Payload: payload}) + created, err := client.Command(t.Context(), protocol.CommandParams{CommandID: "update-smoke-create", Scope: "daemon", Operation: "session.create", Payload: payload}) if err != nil || created.Status != "succeeded" { t.Fatalf("create session: %+v, %v", created, err) } diff --git a/cmd/whip/gateway_process.go b/cmd/whip/gateway_process.go index 698531b5c..2d84cead0 100644 --- a/cmd/whip/gateway_process.go +++ b/cmd/whip/gateway_process.go @@ -17,7 +17,7 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" - "github.com/context-labs/whip/internal/daemon" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webgateway" @@ -196,7 +196,7 @@ func manageGateway(ctx context.Context, paths daemonconn.RuntimePaths, generatio defer cancel() // Socket readiness cannot wait for gateway readiness: the gateway itself // needs to initialize against this socket. Only CLI managed-start waits for both. - var client *daemon.Client + var client *daemonclient.Client var err error ticker := time.NewTicker(25 * time.Millisecond) defer ticker.Stop() diff --git a/cmd/whip/main_test.go b/cmd/whip/main_test.go index d7d85cf4a..40dc84d59 100644 --- a/cmd/whip/main_test.go +++ b/cmd/whip/main_test.go @@ -15,9 +15,10 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -320,16 +321,16 @@ func promptSubmitter(t *testing.T, kind, workingDirectory string) func(string) { } ctx, cancel := context.WithTimeout(t.Context(), 15*time.Second) t.Cleanup(cancel) - var root *daemon.RootClient + var root *daemonclient.RootClient var err error if kind == "acp" { backend := &acpDaemonBackend{clientID: "prompt-acp", model: "test", provider: "testprov"} root, err = backend.NewRoot(ctx, workingDirectory, nil) } else { // Mirror the presentation-only TUI's root creation and submit path. - root, err = daemon.NewRootClient(daemon.RootClientOptions{ + root, err = daemonclient.NewRootClient(daemonclient.RootClientOptions{ ClientID: "prompt-tui", Connector: daemonConnector("tui", "prompt-tui"), - Create: &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: workingDirectory, Model: "test", Provider: "testprov"}, + Create: &session.CreateSession{Kind: session.SessionKindAgent, CWD: workingDirectory, Model: "test", Provider: "testprov"}, }) if err == nil { root.Start() @@ -345,7 +346,7 @@ func promptSubmitter(t *testing.T, kind, workingDirectory string) func(string) { t.Cleanup(func() { _ = root.Close() }) return func(text string) { t.Helper() - action, err := root.NewAction("submit", daemon.SubmitPayload{Text: text}) + action, err := root.NewAction("submit", protocol.SubmitPayload{Text: text}) if err != nil { t.Fatal(err) } diff --git a/cmd/whip/mcp.go b/cmd/whip/mcp.go index 9b268caeb..e154ea168 100644 --- a/cmd/whip/mcp.go +++ b/cmd/whip/mcp.go @@ -10,8 +10,8 @@ import ( "strings" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/session" @@ -151,9 +151,9 @@ func mcpServe(version string) error { } ctx := context.Background() clientID := daemonClientID("mcp") - client, err := daemon.NewRootClient(daemon.RootClientOptions{ + client, err := daemonclient.NewRootClient(daemonclient.RootClientOptions{ ClientID: clientID, - Create: &daemon.CreateSession{Kind: session.SessionKindToolHost, CWD: wd}, + Create: &session.CreateSession{Kind: session.SessionKindToolHost, CWD: wd}, Connector: daemonConnector("automation", clientID), }) if err != nil { @@ -181,7 +181,7 @@ func mcpServe(version string) error { return errors.Join(serveErr, closeErr, deleteErr) } -type daemonMCPTools struct{ client *daemon.RootClient } +type daemonMCPTools struct{ client *daemonclient.RootClient } func (p daemonMCPTools) ToolDefinitions(ctx context.Context) ([]llm.Tool, error) { action, err := p.client.NewAction("tool.schema", struct{}{}) diff --git a/cmd/whip/run.go b/cmd/whip/run.go index 4d98f3e13..083578a3b 100644 --- a/cmd/whip/run.go +++ b/cmd/whip/run.go @@ -19,9 +19,9 @@ import ( "time" "github.com/context-labs/whip/internal/agentdef" - + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -136,15 +136,15 @@ func runCLI(args []string) error { } clientID := daemonClientID("run") - options := daemon.RootClientOptions{ + options := daemonclient.RootClientOptions{ ClientID: clientID, RootID: *resumeFlag, Connector: daemonConnector("automation", clientID), } if *resumeFlag == "" { - options.Create = &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: cwd(), Model: modelName, Provider: providerName, ExecutionEngine: *engineFlag, PermissionMode: *permissionFlag, Definition: *agentFlag} + options.Create = &session.CreateSession{Kind: session.SessionKindAgent, CWD: cwd(), Model: modelName, Provider: providerName, ExecutionEngine: *engineFlag, PermissionMode: *permissionFlag, Definition: *agentFlag} } - client, err := daemon.NewRootClient(options) + client, err := daemonclient.NewRootClient(options) if err != nil { return err } @@ -219,12 +219,12 @@ func runCLI(args []string) error { } baseline := client.Cursor() - action, err := client.NewAction("submit", daemon.SubmitPayload{Text: prompt}) + action, err := client.NewAction("submit", protocol.SubmitPayload{Text: prompt}) if err != nil { return err } type commandReply struct { - result daemon.CommandResult + result protocol.CommandResult err error } replies := make(chan commandReply, 1) @@ -301,8 +301,8 @@ func newRunOutput(format string, quiet bool) *runOutput { return output } -func (o *runOutput) event(event daemon.ProtocolEvent) { - var stream daemon.StreamEvent +func (o *runOutput) event(event protocol.ProtocolEvent) { + var stream protocol.StreamEvent if strings.HasPrefix(event.Kind, "stream.") { if err := json.Unmarshal(event.Payload, &stream); err != nil { return @@ -384,7 +384,7 @@ func runContextError(err error, timeout time.Duration) error { return err } -func cancelRun(client *daemon.RootClient, rootID string) { +func cancelRun(client *daemonclient.RootClient, rootID string) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() action, err := client.NewAction("cancel", map[string]string{}) @@ -411,7 +411,7 @@ func deleteDaemonSession(clientID, rootID string) error { if err != nil { return err } - result, err := connection.Command(ctx, daemon.CommandParams{ + result, err := connection.Command(ctx, protocol.CommandParams{ CommandID: cleanupID + "-delete-" + rootID, Scope: string(session.CommandScopeDaemon), Operation: "session.delete", diff --git a/cmd/whip/run_output_test.go b/cmd/whip/run_output_test.go index 256550984..ebce92e59 100644 --- a/cmd/whip/run_output_test.go +++ b/cmd/whip/run_output_test.go @@ -8,13 +8,13 @@ import ( "strings" "testing" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" ) func TestRunJSONOutputPreservesToolAndPendingEvents(t *testing.T) { var output bytes.Buffer run := &runOutput{enc: json.NewEncoder(&output)} - for _, event := range []daemon.ProtocolEvent{ + for _, event := range []protocol.ProtocolEvent{ {Kind: "stream.text", Payload: json.RawMessage(`{"text":"first"}`)}, {Kind: "stream.reasoning", Payload: json.RawMessage(`{"text":"considering"}`)}, {Kind: "stream.tool.started", Payload: json.RawMessage(`{"name":"read_file","args":"{\"path\":\"x.txt\"}"}`)}, @@ -55,10 +55,10 @@ func TestRunTextOutputReportsPendingInputUnlessQuiet(t *testing.T) { stderr := captureStderr(t, func() { stdout = captureStdout(t, func() { output := newRunOutput("text", quiet) - output.event(daemon.ProtocolEvent{Kind: "stream.text", Payload: json.RawMessage(`{"text":"answer"}`)}) - output.event(daemon.ProtocolEvent{Kind: "stream.tool.started", Payload: json.RawMessage(`{"name":"read_file"}`)}) - output.event(daemon.ProtocolEvent{Kind: "permission.pending", Payload: json.RawMessage(`{"path":"outside.txt"}`)}) - output.event(daemon.ProtocolEvent{Kind: "question.pending", Payload: json.RawMessage(`{"question":"Continue?"}`)}) + output.event(protocol.ProtocolEvent{Kind: "stream.text", Payload: json.RawMessage(`{"text":"answer"}`)}) + output.event(protocol.ProtocolEvent{Kind: "stream.tool.started", Payload: json.RawMessage(`{"name":"read_file"}`)}) + output.event(protocol.ProtocolEvent{Kind: "permission.pending", Payload: json.RawMessage(`{"path":"outside.txt"}`)}) + output.event(protocol.ProtocolEvent{Kind: "question.pending", Payload: json.RawMessage(`{"question":"Continue?"}`)}) output.finish("answer", nil) }) }) diff --git a/cmd/whip/sessions.go b/cmd/whip/sessions.go index c8c102441..73236504d 100644 --- a/cmd/whip/sessions.go +++ b/cmd/whip/sessions.go @@ -8,7 +8,7 @@ import ( "fmt" "time" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -32,7 +32,7 @@ func sessionsCLI() error { if err != nil { return err } - result, err := connection.Command(ctx, daemon.CommandParams{ + result, err := connection.Command(ctx, protocol.CommandParams{ CommandID: daemonCommandID(clientID, "list"), Scope: string(session.CommandScopeDaemon), Operation: "session.list", Payload: payload, }) diff --git a/cmd/whip/sessions_export.go b/cmd/whip/sessions_export.go index 9eb04ecbd..5de0414b2 100644 --- a/cmd/whip/sessions_export.go +++ b/cmd/whip/sessions_export.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -100,14 +100,14 @@ type rpcCaller interface { Call(ctx context.Context, method string, params, result any) error } -func readExportContent(ctx context.Context, caller rpcCaller, root string, handle daemon.ContentHandle) ([]byte, error) { +func readExportContent(ctx context.Context, caller rpcCaller, root string, handle protocol.ContentHandle) ([]byte, error) { if handle.ReferenceID == "" { return nil, errors.New("the daemon returned an empty export") } data := make([]byte, 0, handle.Size) for offset := int64(0); offset < handle.Size; { var page protocol.ContentReadResult - if err := caller.Call(ctx, "content.read", protocol.ContentReadParams{RootID: root, ReferenceID: handle.ReferenceID, Offset: offset, Limit: daemon.MaxContentChunk}, &page); err != nil { + if err := caller.Call(ctx, "content.read", protocol.ContentReadParams{RootID: root, ReferenceID: handle.ReferenceID, Offset: offset, Limit: daemonconn.MaxContentChunk}, &page); err != nil { return nil, err } if len(page.Data) == 0 { diff --git a/cmd/whip/sessions_export_test.go b/cmd/whip/sessions_export_test.go index 04486df71..90bdb2219 100644 --- a/cmd/whip/sessions_export_test.go +++ b/cmd/whip/sessions_export_test.go @@ -14,7 +14,7 @@ import ( "testing" "time" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -39,13 +39,13 @@ func (c *fakeCaller) Call(_ context.Context, method string, params, result any) } func TestReadExportContentPagesThroughTheReference(t *testing.T) { - payload := []byte(strings.Repeat("x", daemon.MaxContentChunk*2+17)) + payload := []byte(strings.Repeat("x", daemonconn.MaxContentChunk*2+17)) caller := &fakeCaller{data: payload} - data, err := readExportContent(context.Background(), caller, "root", daemon.ContentHandle{ReferenceID: "ref", Size: int64(len(payload))}) + data, err := readExportContent(context.Background(), caller, "root", protocol.ContentHandle{ReferenceID: "ref", Size: int64(len(payload))}) if err != nil || string(data) != string(payload) || caller.calls != 3 { t.Fatalf("paged read: %d bytes over %d calls, err=%v", len(data), caller.calls, err) } - if _, err := readExportContent(context.Background(), caller, "root", daemon.ContentHandle{}); err == nil { + if _, err := readExportContent(context.Background(), caller, "root", protocol.ContentHandle{}); err == nil { t.Fatal("an empty reference must be an error, not an empty export") } } diff --git a/cmd/whip/update.go b/cmd/whip/update.go index e37c5b70f..efd4355be 100644 --- a/cmd/whip/update.go +++ b/cmd/whip/update.go @@ -11,9 +11,10 @@ import ( "time" "github.com/context-labs/whip/internal/buildinfo" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/update" ) @@ -88,22 +89,22 @@ var restartDaemonAfterUpdate = func() error { } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - client, err := daemon.DialClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, ClientID: fmt.Sprintf("update-%d", os.Getpid()), ClientKind: "automation", + client, err := daemonclient.DialClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, ClientID: fmt.Sprintf("update-%d", os.Getpid()), ClientKind: "automation", }) if err != nil { return nil // no responsive daemon means the next client starts the installed build } defer func() { _ = client.Close() }() payload, _ := json.Marshal(map[string]string{"reason": "binary updated"}) - result, err := client.Command(ctx, daemon.CommandParams{ + result, err := client.Command(ctx, protocol.CommandParams{ CommandID: fmt.Sprintf("update-%d", time.Now().UnixNano()), Scope: "daemon", Operation: "daemon.checkpoint", Payload: payload, }) if err != nil { return err } - var notice daemon.RestartNotice + var notice protocol.RestartNotice if err := json.Unmarshal([]byte(result.Output), ¬ice); err != nil { return err } diff --git a/cmd/whip/web.go b/cmd/whip/web.go index 0d8d5aed6..b14c982cf 100644 --- a/cmd/whip/web.go +++ b/cmd/whip/web.go @@ -17,7 +17,7 @@ import ( "syscall" "time" - "github.com/context-labs/whip/internal/daemon" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webassets" @@ -128,9 +128,9 @@ func runGateway(ctx context.Context, paths daemonconn.RuntimePaths, expected *ga } } -func dialGatewayClient(ctx context.Context, paths daemonconn.RuntimePaths) (*daemon.Client, error) { - client, err := daemon.DialClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: version, +func dialGatewayClient(ctx context.Context, paths daemonconn.RuntimePaths) (*daemonclient.Client, error) { + client, err := daemonclient.DialClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: version, ClientID: daemonClientID("web-gateway"), ClientKind: "automation", Capabilities: []string{protocol.NetworkClientCapability}, }) @@ -191,7 +191,7 @@ func checkWebAssets(ctx context.Context, endpoint string) error { if err := json.NewDecoder(io.LimitReader(response.Body, 4096)).Decode(&info); err != nil { return fmt.Errorf("invalid gateway web discovery: %w", err) } - if info.ProtocolMajor != daemon.ProtocolMajor || info.WebSocketPath != "/api/v3/ws" || info.ContentPath != "/api/v3/content/" { + if info.ProtocolMajor != protocol.Major || info.WebSocketPath != "/api/v3/ws" || info.ContentPath != "/api/v3/content/" { return errors.New("gateway web protocol is incompatible; update the gateway executable") } if !info.Available { diff --git a/cmd/whip/web_test.go b/cmd/whip/web_test.go index f08b7da5d..4ccfcb102 100644 --- a/cmd/whip/web_test.go +++ b/cmd/whip/web_test.go @@ -17,7 +17,6 @@ import ( "testing" "time" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/protocoltransport" @@ -55,7 +54,7 @@ func TestWebCLIExplicitURLNeverStartsRuntime(t *testing.T) { if r.URL.Path != "/api/v3/web" { t.Errorf("unexpected path %s", r.URL.Path) } - fmt.Fprintf(w, `{"available":true,"protocol_major":%d,"websocket_path":"/api/v3/ws","content_path":"/api/v3/content/"}`, daemon.ProtocolMajor) + fmt.Fprintf(w, `{"available":true,"protocol_major":%d,"websocket_path":"/api/v3/ws","content_path":"/api/v3/content/"}`, protocol.Major) })) defer server.Close() oldOpen, oldLaunch := openWebBrowser, launchManagedDaemon @@ -91,7 +90,7 @@ func TestWebDiscoveryRejectsMissingAndIncompatibleAssets(t *testing.T) { code int body, errorText string }{ - {name: "not packaged", code: 200, body: fmt.Sprintf(`{"available":false,"protocol_major":%d,"websocket_path":"/api/v3/ws","content_path":"/api/v3/content/"}`, daemon.ProtocolMajor), errorText: "without web assets"}, + {name: "not packaged", code: 200, body: fmt.Sprintf(`{"available":false,"protocol_major":%d,"websocket_path":"/api/v3/ws","content_path":"/api/v3/content/"}`, protocol.Major), errorText: "without web assets"}, {name: "old endpoint", code: 404, errorText: "check the URL"}, {name: "host rejected", code: 403, errorText: "WHIPCODE_ALLOWED_HOSTS"}, {name: "major mismatch", code: 200, body: `{"available":true,"protocol_major":1}`, errorText: "incompatible"}, diff --git a/docs/architecture.md b/docs/architecture.md index b14cf2ece..b7c123cf1 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -141,6 +141,7 @@ budgets, and private transcript. | --- | --- | | `internal/protocol`, `packages/protocol` | typed operation/event contract, generated Draft-07 schemas, TypeScript and Ajv | | `internal/daemon` | shared handlers, Unix/WebSocket/HTTP adapters, root actors, recursive runtime, lifecycle | +| `internal/client` | native Go clients, command/event handling, reconnect and service methods using the existing protocol and framing; no dependency on daemon implementation | | `internal/daemonconn` | shared runtime paths, validated local dialing, native launch primitives, initialization limits and event envelope; daemon retains ownership locks and lifecycle policy | | `internal/commandpresentation` | shared formatting of stored command results for existing native text presenters | | `internal/provider` | host provider configuration, discovery, catalogs and account login lifetimes; borrows existing config/auth storage and exposes operations to daemon without importing it | diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index a976dd29f..ff27b32b7 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -182,7 +182,7 @@ new workflow framework, or package per database table. This fits Go's | `internal/session` | SQLite/content persistence, existing durable models, atomic transitions and queries. | No actor or provider construction. Keep existing transaction logic and representations. It may borrow the existing workspace resolver for authority checks. | | Daemon resource owner | One shared process manager and workspace lock coordinator, passed to tools/MCP/runtime as today. | Ownership is explicit; scope and lifetime stay unchanged. Resource implementations remain in `capability`. | | Existing `agent`, `rlm`, `tools`, `capability`, `mcp`, `llm` | Existing model loop primitives, kernels, tools, authority enforcement, integration machinery, provider encoders. | Keep their established responsibilities. No broad modernization sweep. | -| Proposed `internal/client` | Existing Go `Client`/`RootClient` and client service methods. | Existing protocol and framing; no dependency on the server/agent runtime implementation. Mechanical Go caller import changes are allowed; client APIs and behavior remain unchanged. | +| `internal/client` | Existing Go `Client`/`RootClient` and client service methods. | Existing protocol and framing; no dependency on the server/agent runtime implementation. Mechanical Go caller import changes are allowed; client APIs and behavior remain unchanged. | | Existing `protocol` and `protocoltransport` | Current public representations, schemas, negotiation, and framing. | Preserve contract and representation ownership. Do not force storage to import protocol and create a cycle. | The desired direction is startup → daemon orchestration → services/storage, @@ -682,6 +682,7 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | | Shared native plumbing (plan PR 7) | `3127d8ef67c3d59cd70f55ad697102e275c2a6fc`, [PR #315](https://github.com/context-labs/whip/pull/315), based on PR #314. | Shared connection primitives and command presentation move without changing client/server policy. The declaration, characterization, full affected-suite and fresh fixed/immediate-base evidence is recorded below. The PR remains unmerged. | | Tagged TUI title fixture repair | `codex/backend-reorg-07a-tui-title-fixture`, based on PR #315 (`3127d8ef67c3d59cd70f55ad697102e275c2a6fc`). | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | +| Native client extraction (plan PR 8) | `codex/backend-reorg-08-native-client`, initially based on PR #315. | Exact implementation/private-test moves and canonical Go import changes pass API/source conservation, full ordinary affected race/PTY suites, named native acceptance, static checks and frozen/immediate-parent compatibility. The separate tagged TUI title fixture fails identically on the unchanged parent and candidate; a separate prerequisite repair is required before publication. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1288,3 +1289,81 @@ schema/migrations and dependency files are unchanged from PR #315. Hosted compatibility and workflow results will record this separate prerequisite's published head and immediate parent; local checks do not stand in for those future results. + + +### PR 8 — Native client implementation ownership + +The eight existing client implementation files and eleven client-only declarations +from mixed daemon files now live in `internal/client`. All 53 exported Client +methods, 43 RootClient methods, five constructors/autostart entry points, state +values, interface methods and option/response fields are preserved. Wire and +storage aliases resolve to the same canonical protocol/session declarations; +framing calls use the existing frozen `protocoltransport` implementation directly. +No runtime forwarding client implementation remains in daemon. + +The client borrows the neutral connection primitives introduced in PR 7. Its +command IDs, event ordering, reconnect/snapshot behavior, cancellation targets, +provider mutation no-replay policy, buffers and timeouts are unchanged. Server +handlers and `client_control.go` remain daemon-owned. CLI composes the server +where needed; TUI and ACP consume the client and existing protocol types without +importing daemon implementation. A new production-import guard enforces these +four directions, and the existing provider-call guard also scans client while +retaining its exact AgentSession exception. + +All 23 selected existing private tests and PR 7's fill characterization move with +their implementation. The real expired-cursor snapshot integration test, scoped +service/provider tests and SDK fixture remain in daemon. A test-only frame writer +retains the exact marshal/write sequence. Three fake RPC failures become exact +canonical error literals, preserving their codes, messages and ErrorData.Kind. +The existing runtime/Taskfile shared-package command gains client, and the named +reconnect acceptance command gains its new package without changing its regex. + +Fresh typed analysis at the reviewed PR 7 head records 234 declaration groups, +24 selected tests and exact source hashes. The transform uses AST spans and 794 +resolved identifier-use locations. The API comparison expands aliases and +normalizes only approved declaration ownership: 123 public entries plus the +private callResponse shape match. Source conservation covers 1,305 declarations +across 109 files, including 1,012 function bodies and 344 named tests, after the +recorded extraction and reference edits. It rejects unaccounted added declarations +and changed/untracked Go files; external extra-declaration and extra-file +mutations both fail. The new architecture guard is compared with its exact +reviewed body. Imports and comments are outside that token comparison; the +baseline snapshot retains original full source, comment spans and hashes. +Evidence lives under `/private/tmp/whip-pr8-*`, including the typed baseline, +transform journal, API/declaration conservation logs and proof mutation log. +An external test overlay also compared all three replacement error frames +byte-for-byte with the parent server constructors, including ErrorData.Kind; +all matched (`/private/tmp/whip-pr8-rpc-fixture-bytes.log`). + +On the original PR 7 parent, full race/shuffle passed for client (1.472s), daemon +(273.502s), daemonconn (2.508s), commandpresentation (1.950s), session (154.258s), +ACP (3.612s) and CLI (71.013s). Full TUI race/shuffle passed in a real PTY +(16.150s). Both named reconnect/session and CLI/TUI/ACP Taskfile acceptance +commands passed with their existing assertions. Module build, vet, whipvet, +integration-tag fixture compilation and pinned golangci-lint 2.13.1 passed; lint +reported zero issues. All 36 workflow policy tests passed (56.580s). + +The additional tagged `TestInteractiveSessionOverTrustedProtocol` gate failed on +both transports: the snapshot title was the prompt-derived `Investigate workers`, +while the fixture expected `Worker Investigation`. The same unchanged test failed +on clean PR 7 in a real PTY. Its fake implements GenerateTitle(context.Context), +but the existing runtime uses GenerateTitle(context.Context, string); its +19-character prompt also falls below the existing 20-rune generation threshold. +The provisional title event precedes generated-title completion. These inherited +fixture issues require a separate test-only prerequisite, without changing title +policy, increasing timeouts or weakening the final title assertion. The original +and parent failures are retained in `/private/tmp/whip-pr8-native-acceptance.log` +and `/private/tmp/whip-pr8-parent-native-title.log`; PR 8 does not repair them. + +The initial fresh fixed-SDK/immediate-parent guard passed at +`/private/tmp/whip-pr8-compat-fresh/evidence.json`, with candidate HEAD and immediate +parent both recorded as PR 7's commit and the complete staged extraction diff. +It compared freshly generated artifacts, both transports' response/error/ordered +event transcripts, mutation rejection, lifecycle behavior and both-engine +root/child/content/schema/trace rollback. Toolchains were Go 1.27.0 darwin/arm64 +and Node 24.14.1; fixed SDK/backend stays +`271c0f8d2a35648d1b45056d57432590b783483c`. Candidate test binary SHA-256 was +`8cfe4b022e942473a7f7a1b45c7f2b687a271346586375ed5ce80785f3d4ae6e`. +Publication remains on hold for the separate fixture repair, followed by a +rebase, refreshed immediate-parent proof and compatibility evidence. This entry +does not claim that the inherited tagged gate passed. diff --git a/docs/features.md b/docs/features.md index 11df8811b..68692f078 100644 --- a/docs/features.md +++ b/docs/features.md @@ -442,12 +442,13 @@ backend installation and the existing connection owner in one action. Existing installations, advanced diagnostics and remote hosts retain their policies. Code: `internal/provider/provider_selection.go`, `internal/provider/provider_service.go`, -`internal/tui/{setup,startup}.go`, `internal/daemon/root_client.go`, +`internal/tui/{setup,startup}.go`, `internal/client/root_client.go`, `internal/session/command.go`, `packages/app/src/{provider-setup,welcome,welcome-submission,runtime}.ts*`, `packages/app/src/host-dialog.tsx`, and `apps/desktop/src/runtime.ts`. Tests: `internal/provider/provider_selection_test.go`, -`internal/daemon/{provider_selection,root_client}_test.go`, +`internal/daemon/provider_selection_test.go`, `internal/client/root_client_test.go`, +`internal/daemon/root_client_test.go` (expired-cursor server integration), `internal/tui/{setup,startup,client,cursor}_test.go`, `internal/session/command_test.go`, `cmd/whip/daemon_test.go`, `packages/app/test/{provider-connections,welcome-submission,sidebar-creation,runtime,local-runtime}.test.ts*`, @@ -618,7 +619,8 @@ verified tools, helpers, a child, images, title/compaction and restart recovery. - Provider setup/login, versioned configuration updates and completion execute on the daemon host. TUI themes/keybindings remain local. Secret credentials and ephemeral terminal input are excluded from command journals. -- Implementation: `internal/protocol`, `internal/daemon/{server,subscription, +- Implementation: `internal/protocol`, `internal/client`, `internal/daemonconn`, + `internal/daemon/{server,subscription, transport,completion}.go`, `internal/provider/provider_service.go`, `internal/webgateway`, `internal/session`, and `packages/protocol`. Coverage: `v2_acceptance_test.go`, `runtime_parity_test.go`, `transport_test.go`, `client_admission_test.go`, provider/config tests and the diff --git a/internal/acp/bridge.go b/internal/acp/bridge.go index 1ddc2aa77..8abe0ed24 100644 --- a/internal/acp/bridge.go +++ b/internal/acp/bridge.go @@ -13,9 +13,10 @@ import ( "sync" "time" - acp "github.com/coder/acp-go-sdk" + daemonclient "github.com/context-labs/whip/internal/client" + "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/daemon" + acp "github.com/coder/acp-go-sdk" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/session" ) @@ -34,8 +35,8 @@ var modes = []acp.SessionMode{ // listing. Implementations may resolve config and credentials, but never hand // an agent, store, tool registry, or process to the ACP bridge. type Backend interface { - NewRoot(context.Context, string, map[string]mcp.ServerConfig) (*daemon.RootClient, error) - LoadRoot(context.Context, string, string, map[string]mcp.ServerConfig) (*daemon.RootClient, error) + NewRoot(context.Context, string, map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) + LoadRoot(context.Context, string, string, map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) ListSessions(context.Context, int) ([]session.Meta, error) } @@ -65,7 +66,7 @@ func (b *Bridge) SetAgentConnection(conn *acp.AgentSideConnection) { b.conn = co type acpSession struct { id acp.SessionId - root *daemon.RootClient + root *daemonclient.RootClient lifecycle context.Context stop context.CancelFunc @@ -84,7 +85,7 @@ type acpSession struct { type toolInput struct{ name, args string } -func newACPSession(root *daemon.RootClient, snapshot session.RootSnapshot) *acpSession { +func newACPSession(root *daemonclient.RootClient, snapshot session.RootSnapshot) *acpSession { lifecycle, stop := context.WithCancel(context.Background()) return &acpSession{ id: acp.SessionId(root.RootID()), root: root, lifecycle: lifecycle, stop: stop, @@ -281,7 +282,7 @@ func (b *Bridge) LoadSession(ctx context.Context, params acp.LoadSessionRequest) } } for _, event := range snapshot.Presentation { - b.consumeEvent(s, daemon.ProtocolEvent{RootID: snapshot.RootID, Seq: event.Seq, Kind: event.Kind, Payload: event.Payload}) + b.consumeEvent(s, protocol.ProtocolEvent{RootID: snapshot.RootID, Seq: event.Seq, Kind: event.Kind, Payload: event.Payload}) } if err := b.register(s); err != nil { s.stop() @@ -425,7 +426,7 @@ func (b *Bridge) Prompt(_ context.Context, params acp.PromptRequest) (acp.Prompt s.mu.Unlock() text, parts := promptFromBlocks(params.Prompt, b.vision) - action, err := s.root.NewAction("submit", daemon.SubmitPayload{Text: text, Parts: parts}) + action, err := s.root.NewAction("submit", protocol.SubmitPayload{Text: text, Parts: parts}) if err != nil { return acp.PromptResponse{}, acp.NewInternalError(err.Error()) } @@ -499,8 +500,8 @@ func (b *Bridge) consume(s *acpSession) { } } -func (b *Bridge) consumeEvent(s *acpSession, event daemon.ProtocolEvent) { - var stream daemon.StreamEvent +func (b *Bridge) consumeEvent(s *acpSession, event protocol.ProtocolEvent) { + var stream protocol.StreamEvent if strings.HasPrefix(event.Kind, "stream.") { if err := json.Unmarshal(event.Payload, &stream); err != nil { return @@ -508,7 +509,7 @@ func (b *Bridge) consumeEvent(s *acpSession, event daemon.ProtocolEvent) { } switch event.Kind { case "session.permission_mode.updated": - var update daemon.SessionUpdateEvent + var update protocol.SessionUpdateEvent if json.Unmarshal(event.Payload, &update) == nil && update.PermissionMode != nil { b.applyPermissionMode(s, *update.PermissionMode, event.Seq) } @@ -537,7 +538,7 @@ func (b *Bridge) consumeEvent(s *acpSession, event daemon.ProtocolEvent) { }}) } case "stream.plan": - var plan daemon.PlanEvent + var plan protocol.PlanEvent if json.Unmarshal([]byte(stream.Result), &plan) == nil { entries := make([]acp.PlanEntry, 0, len(plan.Items)) for _, item := range plan.Items { diff --git a/internal/acp/bridge_test.go b/internal/acp/bridge_test.go index 0c8efd570..5bbf94773 100644 --- a/internal/acp/bridge_test.go +++ b/internal/acp/bridge_test.go @@ -11,9 +11,10 @@ import ( "testing" "time" - acpsdk "github.com/coder/acp-go-sdk" + daemonclient "github.com/context-labs/whip/internal/client" + "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/daemon" + acpsdk "github.com/coder/acp-go-sdk" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/session" @@ -34,7 +35,7 @@ type fakeRoot struct { cwd string title string messages []llm.Message - events []daemon.ProtocolEvent + events []protocol.ProtocolEvent presentation []session.SnapshotEvent permissions []session.PermissionSnapshot remember string @@ -44,7 +45,7 @@ type fakeRoot struct { snapshotError string snapshotCalls int connections []*fakeConnection - lastSubmit daemon.SubmitPayload + lastSubmit protocol.SubmitPayload lastAnswer questionAnswer questions []session.LifecycleEvent // open user.ask prompts a snapshot lists cancel chan struct{} @@ -59,7 +60,7 @@ func newFakeBackend(t *testing.T) *fakeACPBackend { return &fakeACPBackend{roots: make(map[string]*fakeRoot), attached: make(map[string]map[string]mcp.ServerConfig)} } -func (b *fakeACPBackend) NewRoot(ctx context.Context, cwd string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *fakeACPBackend) NewRoot(ctx context.Context, cwd string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { if b.newErr != nil { return nil, b.newErr } @@ -76,7 +77,7 @@ func (b *fakeACPBackend) NewRoot(ctx context.Context, cwd string, servers map[st return b.client(ctx, root) } -func (b *fakeACPBackend) LoadRoot(ctx context.Context, id, _ string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *fakeACPBackend) LoadRoot(ctx context.Context, id, _ string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { b.mu.Lock() root := b.roots[id] if root != nil { @@ -89,10 +90,10 @@ func (b *fakeACPBackend) LoadRoot(ctx context.Context, id, _ string, servers map return b.client(ctx, root) } -func (b *fakeACPBackend) client(ctx context.Context, root *fakeRoot) (*daemon.RootClient, error) { - client, err := daemon.NewRootClient(daemon.RootClientOptions{ +func (b *fakeACPBackend) client(ctx context.Context, root *fakeRoot) (*daemonclient.RootClient, error) { + client, err := daemonclient.NewRootClient(daemonclient.RootClientOptions{ ClientID: "acp-test", RootID: root.id, - Connector: func(context.Context, map[string]int64) (daemon.RootConnection, error) { + Connector: func(context.Context, map[string]int64) (daemonclient.RootConnection, error) { return newFakeConnection(root), nil }, RetryMin: time.Millisecond, RetryMax: 5 * time.Millisecond, @@ -137,21 +138,21 @@ func (b *fakeACPBackend) seed(cwd string, messages ...llm.Message) string { type fakeConnection struct { root *fakeRoot - events chan daemon.ProtocolEvent + events chan protocol.ProtocolEvent done chan struct{} once sync.Once } func newFakeConnection(root *fakeRoot) *fakeConnection { - connection := &fakeConnection{root: root, events: make(chan daemon.ProtocolEvent, 64), done: make(chan struct{})} + connection := &fakeConnection{root: root, events: make(chan protocol.ProtocolEvent, 64), done: make(chan struct{})} root.mu.Lock() root.connections = append(root.connections, connection) root.mu.Unlock() return connection } -func (c *fakeConnection) Command(ctx context.Context, params daemon.CommandParams) (daemon.CommandResult, error) { - result := daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded"} +func (c *fakeConnection) Command(ctx context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + result := protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded"} switch params.Operation { case "permission.mode": c.root.mu.Lock() @@ -173,7 +174,7 @@ func (c *fakeConnection) Command(ctx context.Context, params daemon.CommandParam if payload.External { mode = "prompt" } - update, _ := json.Marshal(daemon.SessionUpdateEvent{PermissionMode: &mode}) + update, _ := json.Marshal(protocol.SessionUpdateEvent{PermissionMode: &mode}) c.emitRaw("session.permission_mode.updated", update) return result, nil case "cancel": @@ -187,7 +188,7 @@ func (c *fakeConnection) Command(ctx context.Context, params daemon.CommandParam case "question.answer": var answer questionAnswer if err := json.Unmarshal(params.Payload, &answer); err != nil { - return daemon.CommandResult{}, err + return protocol.CommandResult{}, err } c.root.mu.Lock() c.root.lastAnswer = answer @@ -202,22 +203,22 @@ func (c *fakeConnection) Command(ctx context.Context, params daemon.CommandParam } } -func (c *fakeConnection) submit(ctx context.Context, params daemon.CommandParams, result daemon.CommandResult) (daemon.CommandResult, error) { - var payload daemon.SubmitPayload +func (c *fakeConnection) submit(ctx context.Context, params protocol.CommandParams, result protocol.CommandResult) (protocol.CommandResult, error) { + var payload protocol.SubmitPayload if err := json.Unmarshal(params.Payload, &payload); err != nil { - return daemon.CommandResult{}, err + return protocol.CommandResult{}, err } c.root.mu.Lock() c.root.lastSubmit = payload c.root.messages = append(c.root.messages, llm.Message{Role: "user", Content: payload.Text, Parts: payload.Parts}) c.root.mu.Unlock() if strings.Contains(payload.Text, "events") { - c.emit("stream.reasoning", daemon.StreamEvent{Text: "thinking"}) - c.emit("stream.tool.started", daemon.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a.go"}`}) - c.emit("stream.tool.completed", daemon.StreamEvent{ID: "tool-1", Name: "read", Result: "contents"}) - c.emit("stream.usage", daemon.StreamEvent{Usage: &daemon.UsageEvent{Used: 7, Size: 100}}) - plan, _ := json.Marshal(daemon.PlanEvent{Items: []daemon.PlanItem{{Content: "check", Status: "completed"}}}) - c.emit("stream.plan", daemon.StreamEvent{Result: string(plan)}) + c.emit("stream.reasoning", protocol.StreamEvent{Text: "thinking"}) + c.emit("stream.tool.started", protocol.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a.go"}`}) + c.emit("stream.tool.completed", protocol.StreamEvent{ID: "tool-1", Name: "read", Result: "contents"}) + c.emit("stream.usage", protocol.StreamEvent{Usage: &protocol.UsageEvent{Used: 7, Size: 100}}) + plan, _ := json.Marshal(protocol.PlanEvent{Items: []protocol.PlanItem{{Content: "check", Status: "completed"}}}) + c.emit("stream.plan", protocol.StreamEvent{Result: string(plan)}) } if strings.Contains(payload.Text, "permission") { c.emitRaw("permission.pending", []byte(`{"permission_id":"permission-1","operation_id":"operation-1","operation":"write","canonical_path":"/tmp/a.go","command":"/tmp/a.go","rule":"/tmp/a.go"}`)) @@ -233,7 +234,7 @@ func (c *fakeConnection) submit(ctx context.Context, params daemon.CommandParams c.emitRaw("turn.failed", nil) return result, nil case <-ctx.Done(): - return daemon.CommandResult{}, ctx.Err() + return protocol.CommandResult{}, ctx.Err() } } if strings.Contains(payload.Text, "question") { @@ -241,11 +242,11 @@ func (c *fakeConnection) submit(ctx context.Context, params daemon.CommandParams select { case <-c.root.question: case <-ctx.Done(): - return daemon.CommandResult{}, ctx.Err() + return protocol.CommandResult{}, ctx.Err() } } answer := "answer" - c.emit("stream.text", daemon.StreamEvent{Text: answer}) + c.emit("stream.text", protocol.StreamEvent{Text: answer}) c.root.mu.Lock() c.root.title = "Test session" c.root.messages = append(c.root.messages, llm.Message{Role: "assistant", Content: answer}) @@ -255,7 +256,7 @@ func (c *fakeConnection) submit(ctx context.Context, params daemon.CommandParams return result, nil } -func (c *fakeConnection) emit(kind string, stream daemon.StreamEvent) { +func (c *fakeConnection) emit(kind string, stream protocol.StreamEvent) { payload, _ := json.Marshal(stream) c.emitRaw(kind, payload) } @@ -263,7 +264,7 @@ func (c *fakeConnection) emit(kind string, stream daemon.StreamEvent) { func (c *fakeConnection) emitRaw(kind string, payload []byte) { c.root.mu.Lock() seq := int64(len(c.root.events) + 1) - event := daemon.ProtocolEvent{RootID: c.root.id, Seq: seq, Kind: kind, Payload: payload} + event := protocol.ProtocolEvent{RootID: c.root.id, Seq: seq, Kind: kind, Payload: payload} c.root.events = append(c.root.events, event) connections := append([]*fakeConnection{}, c.root.connections...) c.root.mu.Unlock() @@ -275,10 +276,10 @@ func (c *fakeConnection) emitRaw(kind string, payload []byte) { } } -func (c *fakeConnection) Replay(_ context.Context, params daemon.ReplayParams) (daemon.ReplayResult, error) { +func (c *fakeConnection) Replay(_ context.Context, params protocol.ReplayParams) (protocol.ReplayResult, error) { c.root.mu.Lock() defer c.root.mu.Unlock() - result := daemon.ReplayResult{Latest: int64(len(c.root.events))} + result := protocol.ReplayResult{Latest: int64(len(c.root.events))} for _, event := range c.root.events { if event.Seq > params.Cursor { result.Events = append(result.Events, event) @@ -310,7 +311,7 @@ func (c *fakeConnection) Snapshot(context.Context, string) (session.RootSnapshot }, nil } -func (c *fakeConnection) DecidePermission(_ context.Context, decision daemon.PermissionDecision) (daemon.PermissionDecisionResult, error) { +func (c *fakeConnection) DecidePermission(_ context.Context, decision protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) { c.root.mu.Lock() c.root.decisions++ c.root.remember = decision.Remember @@ -319,12 +320,12 @@ func (c *fakeConnection) DecidePermission(_ context.Context, decision daemon.Per case c.root.permission <- decision.Allow: default: } - return daemon.PermissionDecisionResult{OperationID: "operation-1"}, nil + return protocol.PermissionDecisionResult{OperationID: "operation-1"}, nil } -func (c *fakeConnection) Events() <-chan daemon.ProtocolEvent { return c.events } -func (c *fakeConnection) Done() <-chan struct{} { return c.done } -func (c *fakeConnection) Err() error { return nil } +func (c *fakeConnection) Events() <-chan protocol.ProtocolEvent { return c.events } +func (c *fakeConnection) Done() <-chan struct{} { return c.done } +func (c *fakeConnection) Err() error { return nil } func (c *fakeConnection) Close() error { c.once.Do(func() { c.root.mu.Lock() @@ -549,7 +550,7 @@ func TestBridgeLoadReplaysBeforeResponseAndLists(t *testing.T) { llm.Message{Role: "user", Content: "remember"}, llm.Message{Role: "assistant", Content: "remembered"}, ) - presentation, _ := json.Marshal(daemon.StreamEvent{Text: "unfinished thought"}) + presentation, _ := json.Marshal(protocol.StreamEvent{Text: "unfinished thought"}) backend.roots[id].presentation = []session.SnapshotEvent{{Seq: 1, Kind: "stream.reasoning", Payload: presentation}} fixture := newACPFixture(t, backend, nil) fixture.initialize(t) @@ -851,7 +852,7 @@ func TestBridgeConcurrentSessionsAndCloseDetach(t *testing.T) { func TestFakeConnectionImplementsRootProtocol(t *testing.T) { root := &fakeRoot{id: "root", cancel: make(chan struct{}, 1), permission: make(chan bool, 1)} - var _ daemon.RootConnection = newFakeConnection(root) + var _ daemonclient.RootConnection = newFakeConnection(root) } func TestBridgeRejectsUnsupportedAndInvalidProtocolRequests(t *testing.T) { @@ -965,8 +966,8 @@ func TestBridgeSessionRequestErrorsRemainSessionScoped(t *testing.T) { } } -func (*fakeConnection) Subscribe(context.Context, string, int64) (daemon.SubscribeResult, error) { - return daemon.SubscribeResult{}, nil +func (*fakeConnection) Subscribe(context.Context, string, int64) (protocol.SubscribeResult, error) { + return protocol.SubscribeResult{}, nil } func TestBridgeCancelsWhilePermissionDecisionIsPending(t *testing.T) { diff --git a/internal/acp/session_cleanup_test.go b/internal/acp/session_cleanup_test.go index 95a881b9e..336378fc5 100644 --- a/internal/acp/session_cleanup_test.go +++ b/internal/acp/session_cleanup_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - acpsdk "github.com/coder/acp-go-sdk" + daemonclient "github.com/context-labs/whip/internal/client" - "github.com/context-labs/whip/internal/daemon" + acpsdk "github.com/coder/acp-go-sdk" "github.com/context-labs/whip/internal/mcp" ) @@ -15,11 +15,11 @@ type seededACPBackend struct { id string } -func (b *seededACPBackend) NewRoot(ctx context.Context, _ string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *seededACPBackend) NewRoot(ctx context.Context, _ string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { return b.fakeACPBackend.LoadRoot(ctx, b.id, "", servers) } -func (b *seededACPBackend) LoadRoot(ctx context.Context, _, _ string, servers map[string]mcp.ServerConfig) (*daemon.RootClient, error) { +func (b *seededACPBackend) LoadRoot(ctx context.Context, _, _ string, servers map[string]mcp.ServerConfig) (*daemonclient.RootClient, error) { return b.NewRoot(ctx, "", servers) } diff --git a/internal/daemon/autostart.go b/internal/client/autostart.go similarity index 72% rename from internal/daemon/autostart.go rename to internal/client/autostart.go index e62452ffa..48c2fa7fa 100644 --- a/internal/daemon/autostart.go +++ b/internal/client/autostart.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -6,22 +6,23 @@ import ( "time" "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" ) type LaunchDaemon func() error // EnsureClient attaches to a responsive daemon, starting one when the socket // is missing or stale. Losing launch races simply attach to the winner. -func EnsureClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { +func EnsureClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize protocol.InitializeParams, launch LaunchDaemon) (*Client, error) { return awaitClient(ctx, paths, initialize, launch) } -func awaitClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams, launch LaunchDaemon) (*Client, error) { +func awaitClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize protocol.InitializeParams, launch LaunchDaemon) (*Client, error) { client, err := DialClient(ctx, paths, initialize) if err == nil { return client, nil } - if _, rejected := errors.AsType[*RPCError](err); rejected || launch == nil { + if _, rejected := errors.AsType[*protocol.RPCError](err); rejected || launch == nil { return nil, err } if launchErr := launch(); launchErr != nil && !errors.Is(launchErr, daemonconn.ErrDaemonOwned) { @@ -40,7 +41,7 @@ func awaitClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize if err == nil { return client, nil } - if _, rejected := errors.AsType[*RPCError](err); rejected { + if _, rejected := errors.AsType[*protocol.RPCError](err); rejected { return nil, err } delay = min(delay*2, 250*time.Millisecond) diff --git a/internal/client/autostart_test.go b/internal/client/autostart_test.go new file mode 100644 index 000000000..d4f50dc89 --- /dev/null +++ b/internal/client/autostart_test.go @@ -0,0 +1,31 @@ +//go:build unix + +package client + +import ( + "context" + "errors" + "testing" + + "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" +) + +func TestEnsureClientReportsLaunchAndContextFailures(t *testing.T) { + paths, err := daemonconn.Paths(t.TempDir()) + if err != nil { + t.Fatal(err) + } + launchErr := errors.New("launch failed") + if _, err := EnsureClient(context.Background(), paths, protocol.InitializeParams{}, nil); err == nil { + t.Fatal("missing daemon without launcher succeeded") + } + if _, err := EnsureClient(context.Background(), paths, protocol.InitializeParams{}, func() error { return launchErr }); !errors.Is(err, launchErr) { + t.Fatalf("launch failure = %v", err) + } + ctx, cancel := context.WithCancel(context.Background()) + cancel() + if _, err := EnsureClient(ctx, paths, protocol.InitializeParams{}, func() error { return daemonconn.ErrDaemonOwned }); !errors.Is(err, context.Canceled) { + t.Fatalf("cancelled autostart = %v", err) + } +} diff --git a/internal/daemon/client.go b/internal/client/client.go similarity index 72% rename from internal/daemon/client.go rename to internal/client/client.go index 44432e304..8b96bcfa9 100644 --- a/internal/daemon/client.go +++ b/internal/client/client.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -14,6 +14,7 @@ import ( "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/protocoltransport" "github.com/context-labs/whip/internal/session" ) @@ -29,8 +30,8 @@ const ( // Client is one initialized JSON-RPC connection to the local daemon. type Client struct { - conn messageTransport - init InitializeResult + conn protocoltransport.Transport + init protocol.InitializeResult writeMu sync.Mutex mu sync.Mutex @@ -38,13 +39,13 @@ type Client struct { subscriptions map[string]string pending map[string]chan callResponse commandChanged chan struct{} - events chan ProtocolEvent + events chan protocol.ProtocolEvent done chan struct{} err error once sync.Once } -func DialClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize InitializeParams) (*Client, error) { +func DialClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize protocol.InitializeParams) (*Client, error) { timeout := daemonconn.InitializationTimeout if deadline, ok := ctx.Deadline(); ok { timeout = time.Until(deadline) @@ -64,26 +65,26 @@ func DialClient(ctx context.Context, paths daemonconn.RuntimePaths, initialize I return client, nil } -func NewClient(ctx context.Context, conn net.Conn, initialize InitializeParams) (*Client, error) { +func NewClient(ctx context.Context, conn net.Conn, initialize protocol.InitializeParams) (*Client, error) { if conn == nil { return nil, errors.New("protocol connection is required") } - return newTransportClient(ctx, newUnixMessageTransport(conn), initialize) + return newTransportClient(ctx, protocoltransport.NewUnix(conn), initialize) } -func newTransportClient(ctx context.Context, conn messageTransport, initialize InitializeParams) (*Client, error) { +func newTransportClient(ctx context.Context, conn protocoltransport.Transport, initialize protocol.InitializeParams) (*Client, error) { if conn == nil { return nil, errors.New("protocol connection is required") } client := &Client{ conn: conn, subscriptions: make(map[string]string), nextID: 1, pending: make(map[string]chan callResponse), - commandChanged: make(chan struct{}), events: make(chan ProtocolEvent, MaxOutboundEnvelopes), done: make(chan struct{}), + commandChanged: make(chan struct{}), events: make(chan protocol.ProtocolEvent, daemonconn.MaxOutboundEnvelopes), done: make(chan struct{}), } params, err := json.Marshal(initialize) if err != nil { return nil, err } - frame, err := marshalFrame(rpcMessage{ID: json.RawMessage("1"), Method: "initialize", Params: params}) + frame, err := protocoltransport.MarshalFrame(protocoltransport.Message{ID: json.RawMessage("1"), Method: "initialize", Params: params}) if err != nil { return nil, err } @@ -100,7 +101,7 @@ func newTransportClient(ctx context.Context, conn messageTransport, initialize I if err != nil { return nil, err } - reply, err := decodeFrame(replyFrame) + reply, err := protocoltransport.DecodeFrame(replyFrame) if err != nil { return nil, err } @@ -114,7 +115,7 @@ func newTransportClient(ctx context.Context, conn messageTransport, initialize I if err := json.Unmarshal(raw, &client.init); err != nil { return nil, fmt.Errorf("decode initialize result: %w", err) } - if client.init.ProtocolMajor != ProtocolMajor { + if client.init.ProtocolMajor != protocol.Major { return nil, fmt.Errorf("daemon selected unsupported protocol major %d", client.init.ProtocolMajor) } _ = conn.SetReadDeadline(time.Time{}) @@ -123,7 +124,7 @@ func newTransportClient(ctx context.Context, conn messageTransport, initialize I go client.heartbeat(context.WithoutCancel(ctx), clientPingInterval, clientPingTimeout) for rootID, cursor := range initialize.Cursors { if _, err := client.Subscribe(ctx, rootID, cursor); err != nil { - if failure, ok := errors.AsType[*RPCError](err); ok && failure.Code == -32010 { + if failure, ok := errors.AsType[*protocol.RPCError](err); ok && failure.Code == -32010 { continue } client.close(err) @@ -133,9 +134,9 @@ func newTransportClient(ctx context.Context, conn messageTransport, initialize I return client, nil } -func (c *Client) InitializeResult() InitializeResult { return c.init } +func (c *Client) InitializeResult() protocol.InitializeResult { return c.init } -func (c *Client) Events() <-chan ProtocolEvent { return c.events } +func (c *Client) Events() <-chan protocol.ProtocolEvent { return c.events } func (c *Client) Done() <-chan struct{} { return c.done } @@ -170,7 +171,7 @@ func (c *Client) Call(ctx context.Context, method string, params, result any) er c.pending[id] = response c.mu.Unlock() - frame, err := marshalFrame(rpcMessage{ID: json.RawMessage(id), Method: method, Params: rawParams}) + frame, err := protocoltransport.MarshalFrame(protocoltransport.Message{ID: json.RawMessage(id), Method: method, Params: rawParams}) if err == nil { c.writeMu.Lock() err = c.conn.WriteMessage(frame) @@ -197,23 +198,23 @@ func (c *Client) Call(ctx context.Context, method string, params, result any) er } // Submit accepts durable work without retaining the request until completion. -func (c *Client) Submit(ctx context.Context, params CommandParams) (CommandResult, error) { - var result CommandResult +func (c *Client) Submit(ctx context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + var result protocol.CommandResult err := c.Call(ctx, "command.submit", params, &result) fillCommandPresentation(&result) return result, err } -func (c *Client) CommandStatus(ctx context.Context, commandID string) (CommandResult, error) { - var result CommandResult - err := c.Call(ctx, "command.status", CommandStatusParams{CommandID: commandID}, &result) +func (c *Client) CommandStatus(ctx context.Context, commandID string) (protocol.CommandResult, error) { + var result protocol.CommandResult + err := c.Call(ctx, "command.status", protocol.CommandStatusParams{CommandID: commandID}, &result) fillCommandPresentation(&result) return result, err } // SubmitAndWait is a convenience for callers that need the terminal result. // Cancelling this wait does not cancel the admitted operation. -func (c *Client) SubmitAndWait(ctx context.Context, params CommandParams) (CommandResult, error) { +func (c *Client) SubmitAndWait(ctx context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { result, err := c.Submit(ctx, params) if err != nil { return result, err @@ -221,7 +222,7 @@ func (c *Client) SubmitAndWait(ctx context.Context, params CommandParams) (Comma return c.waitCommand(ctx, params.RootID, result) } -func (c *Client) waitCommand(ctx context.Context, rootID string, result CommandResult) (CommandResult, error) { +func (c *Client) waitCommand(ctx context.Context, rootID string, result protocol.CommandResult) (protocol.CommandResult, error) { var err error ticker := time.NewTicker(50 * time.Millisecond) defer ticker.Stop() @@ -248,31 +249,31 @@ func (c *Client) waitCommand(ctx context.Context, rootID string, result CommandR return result, nil } -func (c *Client) Command(ctx context.Context, params CommandParams) (CommandResult, error) { +func (c *Client) Command(ctx context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { if operation, ok := protocol.LookupRuntime(params.Operation); ok && operation.Execution == protocol.Ephemeral { reply, err := c.Invoke(ctx, protocol.QueryParams{RootID: params.RootID, Operation: params.Operation, Payload: params.Payload}) - result := CommandResult{Operation: params.Operation, Status: "succeeded", Result: reply.Result} + result := protocol.CommandResult{Operation: params.Operation, Status: "succeeded", Result: reply.Result} fillCommandPresentation(&result) return result, err } if operation, ok := protocol.LookupRuntime(params.Operation); ok && operation.Execution == protocol.Query { query, err := c.Query(ctx, protocol.QueryParams{RootID: params.RootID, Operation: params.Operation, Payload: params.Payload}) - result := CommandResult{Operation: params.Operation, CommandID: params.CommandID, Status: "succeeded", Result: query.Result} + result := protocol.CommandResult{Operation: params.Operation, CommandID: params.CommandID, Status: "succeeded", Result: query.Result} fillCommandPresentation(&result) return result, err } return c.SubmitAndWait(ctx, params) } -func (c *Client) Replay(ctx context.Context, params ReplayParams) (ReplayResult, error) { - var result ReplayResult +func (c *Client) Replay(ctx context.Context, params protocol.ReplayParams) (protocol.ReplayResult, error) { + var result protocol.ReplayResult err := c.Call(ctx, "events.replay", params, &result) return result, err } func (c *Client) Snapshot(ctx context.Context, rootID string) (session.RootSnapshot, error) { var snapshot session.RootSnapshot - if err := c.Call(ctx, "root.snapshot", SnapshotParams{RootID: rootID}, &snapshot); err != nil { + if err := c.Call(ctx, "root.snapshot", protocol.SnapshotParams{RootID: rootID}, &snapshot); err != nil { return snapshot, err } if snapshot.RootID != rootID { @@ -281,40 +282,40 @@ func (c *Client) Snapshot(ctx context.Context, rootID string) (session.RootSnaps return snapshot, nil } -func (c *Client) ValidateProvider(ctx context.Context, params ProviderValidateParams) (ProviderValidateResult, error) { - var result ProviderValidateResult +func (c *Client) ValidateProvider(ctx context.Context, params protocol.ProviderValidateParams) (protocol.ProviderValidateResult, error) { + var result protocol.ProviderValidateResult err := c.Call(ctx, "provider.validate", params, &result) return result, err } -func (c *Client) Upload(ctx context.Context, begin UploadBeginParams, data []byte) (ContentHandle, error) { +func (c *Client) Upload(ctx context.Context, begin protocol.UploadBeginParams, data []byte) (protocol.ContentHandle, error) { if int64(len(data)) != begin.Size { - return ContentHandle{}, errors.New("upload data size does not match metadata") + return protocol.ContentHandle{}, errors.New("upload data size does not match metadata") } if err := c.Call(ctx, "upload.begin", begin, nil); err != nil { - return ContentHandle{}, err + return protocol.ContentHandle{}, err } - for offset := 0; offset < len(data); offset += MaxContentChunk { - end := min(offset+MaxContentChunk, len(data)) - if err := c.Call(ctx, "upload.chunk", UploadChunkParams{ + for offset := 0; offset < len(data); offset += daemonconn.MaxContentChunk { + end := min(offset+daemonconn.MaxContentChunk, len(data)) + if err := c.Call(ctx, "upload.chunk", protocol.UploadChunkParams{ UploadID: begin.UploadID, Offset: int64(offset), Data: data[offset:end], }, nil); err != nil { - return ContentHandle{}, err + return protocol.ContentHandle{}, err } } - var handle ContentHandle - if err := c.Call(ctx, "upload.finish", UploadFinishParams{UploadID: begin.UploadID}, &handle); err != nil { - return ContentHandle{}, err + var handle protocol.ContentHandle + if err := c.Call(ctx, "upload.finish", protocol.UploadFinishParams{UploadID: begin.UploadID}, &handle); err != nil { + return protocol.ContentHandle{}, err } return handle, nil } -func (c *Client) DecidePermission(ctx context.Context, decision PermissionDecision) (PermissionDecisionResult, error) { +func (c *Client) DecidePermission(ctx context.Context, decision protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) { if decision.CommandID == "" || decision.RootID == "" || decision.PermissionID == "" { - return PermissionDecisionResult{}, errors.New("permission decision requires command, root, and permission identities") + return protocol.PermissionDecisionResult{}, errors.New("permission decision requires command, root, and permission identities") } - var result PermissionDecisionResult - err := c.Call(ctx, "permission.decide", PermissionDecisionParams{Decision: decision}, &result) + var result protocol.PermissionDecisionResult + err := c.Call(ctx, "permission.decide", protocol.PermissionDecisionParams{Decision: decision}, &result) return result, err } @@ -327,11 +328,11 @@ func (c *Client) RequestStop(ctx context.Context, generation int64) error { } func (c *Client) requestLifecycle(ctx context.Context, method string, generation int64) error { - params, err := json.Marshal(RestartParams{Generation: generation}) + params, err := json.Marshal(protocol.RestartParams{Generation: generation}) if err != nil { return err } - frame, err := marshalFrame(rpcMessage{Method: method, Params: params}) + frame, err := protocoltransport.MarshalFrame(protocoltransport.Message{Method: method, Params: params}) if err != nil { return err } @@ -359,7 +360,7 @@ func (c *Client) readLoop() { c.close(err) return } - message, err := decodeFrame(frame) + message, err := protocoltransport.DecodeFrame(frame) if err != nil { c.close(err) return diff --git a/internal/client/collection.go b/internal/client/collection.go new file mode 100644 index 000000000..67bd63b40 --- /dev/null +++ b/internal/client/collection.go @@ -0,0 +1,26 @@ +package client + +import ( + "context" + + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +func (c *Client) RootCollection(ctx context.Context, params protocol.RootCollectionParams) (session.RootCollectionPage, error) { + var page session.RootCollectionPage + err := c.Call(ctx, "root.collection", params, &page) + return page, err +} + +func (c *Client) SessionCatalog(ctx context.Context, params protocol.SessionCatalogParams) (session.SessionCatalogPage, error) { + var page session.SessionCatalogPage + err := c.Call(ctx, "sessions.list", params, &page) + return page, err +} + +func (c *Client) SessionCatalogRevision(ctx context.Context) (session.CatalogRevision, error) { + var revision session.CatalogRevision + err := c.Call(ctx, "sessions.revision", protocol.EmptyParams{}, &revision) + return revision, err +} diff --git a/internal/client/command_outcome.go b/internal/client/command_outcome.go new file mode 100644 index 000000000..97df25c6a --- /dev/null +++ b/internal/client/command_outcome.go @@ -0,0 +1,13 @@ +package client + +import ( + "github.com/context-labs/whip/internal/commandpresentation" + "github.com/context-labs/whip/internal/protocol" +) + +func fillCommandPresentation(result *protocol.CommandResult) { + result.Output, result.Error = commandpresentation.Decode(result.Operation, result.Result, result.Status) + if result.Failure != nil { + result.Error = result.Failure.Message + } +} diff --git a/internal/client/command_outcome_test.go b/internal/client/command_outcome_test.go new file mode 100644 index 000000000..a0d8ec66a --- /dev/null +++ b/internal/client/command_outcome_test.go @@ -0,0 +1,29 @@ +package client + +import ( + "testing" + + "github.com/context-labs/whip/internal/protocol" +) + +func TestFillCommandPresentation(t *testing.T) { + t.Parallel() + for _, test := range []struct { + name string + result protocol.CommandResult + output, failure string + }{ + {name: "retains output with explicit failure", result: protocol.CommandResult{Operation: "submit", Result: []byte(`{"text":"answer"}`), Failure: &protocol.RPCError{Message: "failure"}}, output: "answer", failure: "failure"}, + {name: "empty explicit failure overrides decode error", result: protocol.CommandResult{Operation: "submit", Result: []byte(`{`), Failure: &protocol.RPCError{}}}, + {name: "nil explicit failure retains decode error", result: protocol.CommandResult{Operation: "submit", Result: []byte(`{`)}, failure: "invalid command result"}, + {name: "empty body clears stale presentation", result: protocol.CommandResult{Operation: "submit", Output: "stale", Error: "stale"}}, + } { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + fillCommandPresentation(&test.result) + if test.result.Output != test.output || test.result.Error != test.failure { + t.Fatalf("presentation = (%q, %q), want (%q, %q)", test.result.Output, test.result.Error, test.output, test.failure) + } + }) + } +} diff --git a/internal/client/completion_client.go b/internal/client/completion_client.go new file mode 100644 index 000000000..1bd20c7ae --- /dev/null +++ b/internal/client/completion_client.go @@ -0,0 +1,19 @@ +package client + +import ( + "context" + + "github.com/context-labs/whip/internal/protocol" +) + +func (c *Client) CompleteWorkspace(ctx context.Context, p protocol.CompletionParams) (protocol.CompletionResult, error) { + var result protocol.CompletionResult + err := c.Call(ctx, "workspace.complete", p, &result) + return result, err +} + +func (c *RootClient) CompleteWorkspace(ctx context.Context, p protocol.CompletionParams) (protocol.CompletionResult, error) { + var result protocol.CompletionResult + err := c.providerCall(ctx, "workspace.complete", p, &result) + return result, err +} diff --git a/internal/daemon/content_client.go b/internal/client/content_client.go similarity index 81% rename from internal/daemon/content_client.go rename to internal/client/content_client.go index 44dfbd4f4..5ddf04ece 100644 --- a/internal/daemon/content_client.go +++ b/internal/client/content_client.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -6,7 +6,9 @@ import ( "encoding/hex" "errors" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" ) func (c *Client) ReadContent(ctx context.Context, params protocol.ContentReadParams) (protocol.ContentReadResult, error) { @@ -15,17 +17,17 @@ func (c *Client) ReadContent(ctx context.Context, params protocol.ContentReadPar return result, err } -func (c *Client) commandContent(ctx context.Context, rootID string, result *CommandResult) error { +func (c *Client) commandContent(ctx context.Context, rootID string, result *protocol.CommandResult) error { if result.Content == nil { return nil } handle := *result.Content - if handle.Size < 0 || handle.Size > MaxUploadSize { + if handle.Size < 0 || handle.Size > session.MaxInputPayloadBytes { return errors.New("command content exceeds transfer limit") } data := make([]byte, 0, int(handle.Size)) for int64(len(data)) < handle.Size { - chunk, err := c.ReadContent(ctx, protocol.ContentReadParams{RootID: rootID, ReferenceID: handle.ReferenceID, Offset: int64(len(data)), Limit: MaxContentChunk}) + chunk, err := c.ReadContent(ctx, protocol.ContentReadParams{RootID: rootID, ReferenceID: handle.ReferenceID, Offset: int64(len(data)), Limit: daemonconn.MaxContentChunk}) if err != nil { return err } diff --git a/internal/daemon/history_client.go b/internal/client/history_client.go similarity index 77% rename from internal/daemon/history_client.go rename to internal/client/history_client.go index 7803e37c8..3d92f811b 100644 --- a/internal/daemon/history_client.go +++ b/internal/client/history_client.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -10,7 +10,7 @@ import ( // HistoryPage reads a bounded raw transcript page without adding it to any // agent's model context. -func (c *RootClient) HistoryPage(ctx context.Context, p HistoryPageParams) (session.BoundedTranscriptPage, error) { +func (c *RootClient) HistoryPage(ctx context.Context, p protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) { if err := c.WaitLive(ctx); err != nil { return session.BoundedTranscriptPage{}, err } @@ -18,7 +18,7 @@ func (c *RootClient) HistoryPage(ctx context.Context, p HistoryPageParams) (sess connection := c.conn c.mu.RUnlock() reader, ok := connection.(interface { - HistoryPage(context.Context, HistoryPageParams) (session.BoundedTranscriptPage, error) + HistoryPage(context.Context, protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) }) if !ok { return session.BoundedTranscriptPage{}, errors.New("daemon does not support transcript pagination") diff --git a/internal/client/invoke.go b/internal/client/invoke.go new file mode 100644 index 000000000..c54b030e3 --- /dev/null +++ b/internal/client/invoke.go @@ -0,0 +1,13 @@ +package client + +import ( + "context" + + "github.com/context-labs/whip/internal/protocol" +) + +func (c *Client) Invoke(ctx context.Context, params protocol.QueryParams) (protocol.QueryResult, error) { + var result protocol.QueryResult + err := c.Call(ctx, "operation.invoke", params, &result) + return result, err +} diff --git a/internal/client/protocol_edge_test.go b/internal/client/protocol_edge_test.go new file mode 100644 index 000000000..98488b819 --- /dev/null +++ b/internal/client/protocol_edge_test.go @@ -0,0 +1,290 @@ +package client + +import ( + "bufio" + "context" + "encoding/json" + "errors" + "net" + "strings" + "testing" + "time" + + "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/protocoltransport" + "github.com/context-labs/whip/internal/session" +) + +func TestClientValidationAndCancellationPaths(t *testing.T) { + if _, err := NewClient(context.Background(), nil, protocol.InitializeParams{}); err == nil { + t.Fatal("nil connection initialized") + } + serverSide, clientSide := net.Pipe() + go func() { + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: protocol.Major}}) + _, _ = protocoltransport.ReadFrame(reader) + _, _ = protocoltransport.ReadFrame(reader) + <-time.After(50 * time.Millisecond) + _ = serverSide.Close() + }() + client, err := NewClient(context.Background(), clientSide, protocol.InitializeParams{ProtocolMajor: protocol.Major}) + if err != nil { + t.Fatal(err) + } + if err := client.Call(context.Background(), "", struct{}{}, nil); err == nil { + t.Fatal("empty method was accepted") + } + if err := client.Call(context.Background(), "invalid.params", make(chan int), nil); err == nil { + t.Fatal("unmarshalable call params were accepted") + } + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) + defer cancel() + if err := client.Call(ctx, "blocked", struct{}{}, nil); !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("cancelled call = %v", err) + } + go client.heartbeat(context.Background(), time.Millisecond, 5*time.Millisecond) + select { + case <-client.Done(): + case <-time.After(100 * time.Millisecond): + t.Fatal("failed heartbeat did not close the client") + } + if err := client.Err(); err == nil || !strings.Contains(err.Error(), "daemon heartbeat") { + t.Fatalf("heartbeat error = %v", err) + } + if err := client.Call(context.Background(), "after.close", struct{}{}, nil); err == nil { + t.Fatal("closed client accepted a call") + } + if err := client.RequestRestart(context.Background(), 1); err == nil { + t.Fatal("closed client requested restart") + } + if _, err := client.Upload(context.Background(), protocol.UploadBeginParams{Size: 2}, []byte("x")); err == nil { + t.Fatal("upload size mismatch was accepted") + } + for _, decision := range []protocol.PermissionDecision{ + {RootID: "root", PermissionID: "permission"}, + {CommandID: "command", PermissionID: "permission"}, + {CommandID: "command", RootID: "root"}, + } { + if _, err := client.DecidePermission(context.Background(), decision); err == nil { + t.Fatalf("incomplete decision identities were accepted: %+v", decision) + } + } + if _, err := client.DecidePermission(context.Background(), protocol.PermissionDecision{ + CommandID: "command", RootID: "root", PermissionID: "permission", Allow: true, + }); err == nil { + t.Fatal("closed client accepted a permission decision") + } +} + +func TestClientRejectsBadInitializeAndSnapshotReplies(t *testing.T) { + for _, result := range []protocoltransport.Message{ + {ID: json.RawMessage("1"), Error: &protocol.RPCError{Code: -1, Message: "refused", Data: &protocol.ErrorData{Kind: "execution_failed"}}}, + {ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: 99}}, + {ID: json.RawMessage("1"), Result: "not-an-initialize-result"}, + } { + serverSide, clientSide := net.Pipe() + go func() { + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, result) + _ = serverSide.Close() + }() + if _, err := NewClient(context.Background(), clientSide, protocol.InitializeParams{ProtocolMajor: protocol.Major}); err == nil { + t.Fatalf("bad initialize reply %+v was accepted", result) + } + } + + for _, result := range []any{session.RootSnapshot{RootID: "other"}, "invalid", struct{}{}} { + serverSide, clientSide := net.Pipe() + go func() { + defer serverSide.Close() + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: protocol.Major}}) + frame, _ := protocoltransport.ReadFrame(reader) + request, _ := protocoltransport.DecodeFrame(frame) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: request.ID, Result: result}) + }() + client, err := NewClient(t.Context(), clientSide, protocol.InitializeParams{ProtocolMajor: protocol.Major}) + if err != nil { + t.Fatal(err) + } + if _, err := client.Snapshot(t.Context(), "root"); err == nil { + t.Fatal("inconsistent snapshot accepted") + } + _ = client.Close() + } +} + +func TestClientConnectionAndReadLoopFailures(t *testing.T) { + closedServer, closedClient := net.Pipe() + _ = closedServer.Close() + if _, err := NewClient(context.Background(), closedClient, protocol.InitializeParams{}); err == nil { + t.Fatal("client initialized across a closed connection") + } + for name, response := range map[string][]byte{ + "eof": nil, + "invalid frame": []byte("{}\n"), + } { + t.Run(name, func(t *testing.T) { + serverSide, clientSide := net.Pipe() + go func() { + _, _ = protocoltransport.ReadFrame(bufio.NewReader(serverSide)) + if response != nil { + _, _ = serverSide.Write(response) + } + _ = serverSide.Close() + }() + if _, err := NewClient(context.Background(), clientSide, protocol.InitializeParams{}); err == nil { + t.Fatal("client accepted a broken initialization response") + } + }) + } + + frames := map[string]protocoltransport.Message{ + "invalid event": {Method: "event", Params: json.RawMessage(`true`)}, + "event overflow": {Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: protocol.ProtocolEvent{RootID: "root", Seq: 2}})}, + "orphan reply": {ID: json.RawMessage("99"), Result: true}, + } + for name, message := range frames { + t.Run(name, func(t *testing.T) { + serverSide, clientSide := net.Pipe() + client := &Client{ + conn: protocoltransport.NewUnix(clientSide), pending: make(map[string]chan callResponse), + commandChanged: make(chan struct{}), events: make(chan protocol.ProtocolEvent, 1), done: make(chan struct{}), + } + if name == "event overflow" { + client.events <- protocol.ProtocolEvent{Seq: 1} + } + frame, err := protocoltransport.MarshalFrame(message) + if err != nil { + t.Fatal(err) + } + written := make(chan struct{}) + go func() { + defer close(written) + defer serverSide.Close() + _, _ = serverSide.Write(frame) + }() + client.readLoop() + <-written + if client.Err() == nil { + t.Fatal("read loop exited without a terminal error") + } + _ = serverSide.Close() + }) + } +} + +func TestClientCallRejectsInvalidResultAndRestartCancellation(t *testing.T) { + serverSide, clientSide := net.Pipe() + go func() { + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: protocol.Major}}) + frame, _ := protocoltransport.ReadFrame(reader) + request, _ := protocoltransport.DecodeFrame(frame) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: request.ID, Result: "wrong shape"}) + _, _ = protocoltransport.ReadFrame(reader) + <-time.After(20 * time.Millisecond) + _ = serverSide.Close() + }() + client, err := NewClient(context.Background(), clientSide, protocol.InitializeParams{}) + if err != nil { + t.Fatal(err) + } + var result map[string]any + if err := client.Call(context.Background(), "invalid.result", struct{}{}, &result); err == nil { + t.Fatal("invalid call result decoded") + } + ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) + defer cancel() + if err := client.RequestRestart(ctx, 1); !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("cancelled restart = %v", err) + } + _ = client.Close() +} + +func TestClientUploadPropagatesEachProtocolFailure(t *testing.T) { + for _, failedMethod := range []string{"upload.begin", "upload.chunk", "upload.finish"} { + t.Run(failedMethod, func(t *testing.T) { + serverSide, clientSide := net.Pipe() + go func() { + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: protocol.Major}}) + for { + frame, err := protocoltransport.ReadFrame(reader) + if err != nil { + return + } + request, _ := protocoltransport.DecodeFrame(frame) + if request.Method == failedMethod { + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: request.ID, Error: &protocol.RPCError{Code: -1, Message: "stopped", Data: &protocol.ErrorData{Kind: "execution_failed"}}}) + return + } + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ID: request.ID, Result: map[string]bool{"accepted": true}}) + } + }() + client, err := NewClient(context.Background(), clientSide, protocol.InitializeParams{}) + if err != nil { + t.Fatal(err) + } + if _, err := client.Upload(context.Background(), protocol.UploadBeginParams{UploadID: "upload", Size: 1}, []byte("x")); err == nil { + t.Fatal("upload protocol failure was ignored") + } + _ = client.Close() + }) + } +} + +func mustJSON(t *testing.T, value any) json.RawMessage { + t.Helper() + raw, err := json.Marshal(value) + if err != nil { + t.Fatal(err) + } + return raw +} + +func TestClientPermissionDecisionUsesUnsignedPayload(t *testing.T) { + serverSide, clientSide := net.Pipe() + requests := make(chan protocoltransport.Message, 1) + go func() { + defer serverSide.Close() + reader := bufio.NewReader(serverSide) + _, _ = protocoltransport.ReadFrame(reader) + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ + ID: json.RawMessage("1"), Result: protocol.InitializeResult{ProtocolMajor: protocol.Major}, + }) + frame, _ := protocoltransport.ReadFrame(reader) + request, _ := protocoltransport.DecodeFrame(frame) + requests <- request + _ = writeProtocolMessage(serverSide, protocoltransport.Message{ + ID: request.ID, Result: protocol.PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, + }) + }() + client, err := NewClient(t.Context(), clientSide, protocol.InitializeParams{ProtocolMajor: protocol.Major}) + if err != nil { + t.Fatal(err) + } + defer client.Close() + decision := protocol.PermissionDecision{ + CommandID: "decision-1", RootID: "root", PermissionID: "permission", + Allow: true, Reason: "approved", Remember: "tree", + } + result, err := client.DecidePermission(t.Context(), decision) + if err != nil || result.OperationID != "operation" || result.LeaseID != "lease" { + t.Fatalf("decision = %+v, %v", result, err) + } + request := <-requests + want := mustJSON(t, struct { + Decision protocol.PermissionDecision `json:"decision"` + }{Decision: decision}) + if request.Method != "permission.decide" || string(request.Params) != string(want) { + t.Fatalf("decision wire message = %s %s, want permission.decide %s", request.Method, request.Params, want) + } +} diff --git a/internal/daemon/provider_client.go b/internal/client/provider_client.go similarity index 90% rename from internal/daemon/provider_client.go rename to internal/client/provider_client.go index b5e069038..479696a17 100644 --- a/internal/daemon/provider_client.go +++ b/internal/client/provider_client.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -67,7 +67,7 @@ func (c *Client) ListProvidersFor(ctx context.Context, model, provider string) ( func (c *Client) DiscoverProviders(ctx context.Context, model, provider string) (protocol.ProviderList, error) { var result protocol.ProviderList err := c.Call(ctx, "provider.discover", protocol.ProviderListParams{Model: model, Provider: provider}, &result) - if failure, ok := errors.AsType[*RPCError](err); ok && failure.Code == -32601 { + if failure, ok := errors.AsType[*protocol.RPCError](err); ok && failure.Code == -32601 { return c.ListProvidersFor(ctx, model, provider) } return result, err @@ -115,31 +115,31 @@ func (c *Client) BeginProviderLogin(ctx context.Context, provider string) (Provi func (c *Client) LoginStatus(ctx context.Context, id string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.Call(ctx, "provider.login.status", ProviderLoginParams{FlowID: id}, &result) + err := c.Call(ctx, "provider.login.status", protocol.ProviderLoginParams{FlowID: id}, &result) return result, err } func (c *Client) CancelLogin(ctx context.Context, id string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.Call(ctx, "provider.login.cancel", ProviderLoginParams{FlowID: id}, &result) + err := c.Call(ctx, "provider.login.cancel", protocol.ProviderLoginParams{FlowID: id}, &result) return result, err } func (c *Client) SelectLoginTeam(ctx context.Context, id, teamID string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.Call(ctx, "provider.login.team.select", ProviderLoginTeamParams{FlowID: id, TeamID: teamID}, &result) + err := c.Call(ctx, "provider.login.team.select", protocol.ProviderLoginTeamParams{FlowID: id, TeamID: teamID}, &result) return result, err } func (c *Client) SelectLoginProject(ctx context.Context, id, projectID string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.Call(ctx, "provider.login.project.select", ProviderLoginProjectParams{FlowID: id, ProjectID: projectID}, &result) + err := c.Call(ctx, "provider.login.project.select", protocol.ProviderLoginProjectParams{FlowID: id, ProjectID: projectID}, &result) return result, err } func (c *Client) CreateLoginProject(ctx context.Context, id, name string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.Call(ctx, "provider.login.project.create", ProviderLoginCreateParams{FlowID: id, Name: name}, &result) + err := c.Call(ctx, "provider.login.project.create", protocol.ProviderLoginCreateParams{FlowID: id, Name: name}, &result) return result, err } @@ -162,7 +162,7 @@ func (c *RootClient) ListProvidersFor(ctx context.Context, model, provider strin func (c *RootClient) DiscoverProviders(ctx context.Context, model, provider string) (protocol.ProviderList, error) { var result protocol.ProviderList err := c.providerCall(ctx, "provider.discover", protocol.ProviderListParams{Model: model, Provider: provider}, &result) - if failure, ok := errors.AsType[*RPCError](err); ok && failure.Code == -32601 { + if failure, ok := errors.AsType[*protocol.RPCError](err); ok && failure.Code == -32601 { return c.ListProvidersFor(ctx, model, provider) } return result, err @@ -214,31 +214,31 @@ func (c *RootClient) BeginProviderLogin(ctx context.Context, provider string) (P func (c *RootClient) LoginStatus(ctx context.Context, id string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.providerCall(ctx, "provider.login.status", ProviderLoginParams{FlowID: id}, &result) + err := c.providerCall(ctx, "provider.login.status", protocol.ProviderLoginParams{FlowID: id}, &result) return result, err } func (c *RootClient) CancelLogin(ctx context.Context, id string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.providerCall(ctx, "provider.login.cancel", ProviderLoginParams{FlowID: id}, &result) + err := c.providerCall(ctx, "provider.login.cancel", protocol.ProviderLoginParams{FlowID: id}, &result) return result, err } func (c *RootClient) SelectLoginTeam(ctx context.Context, id, teamID string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.providerCall(ctx, "provider.login.team.select", ProviderLoginTeamParams{FlowID: id, TeamID: teamID}, &result) + err := c.providerCall(ctx, "provider.login.team.select", protocol.ProviderLoginTeamParams{FlowID: id, TeamID: teamID}, &result) return result, err } func (c *RootClient) SelectLoginProject(ctx context.Context, id, projectID string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.providerCall(ctx, "provider.login.project.select", ProviderLoginProjectParams{FlowID: id, ProjectID: projectID}, &result) + err := c.providerCall(ctx, "provider.login.project.select", protocol.ProviderLoginProjectParams{FlowID: id, ProjectID: projectID}, &result) return result, err } func (c *RootClient) CreateLoginProject(ctx context.Context, id, name string) (ProviderLoginStatus, error) { var result ProviderLoginStatus - err := c.providerCall(ctx, "provider.login.project.create", ProviderLoginCreateParams{FlowID: id, Name: name}, &result) + err := c.providerCall(ctx, "provider.login.project.create", protocol.ProviderLoginCreateParams{FlowID: id, Name: name}, &result) return result, err } diff --git a/internal/client/query.go b/internal/client/query.go new file mode 100644 index 000000000..556ca5e55 --- /dev/null +++ b/internal/client/query.go @@ -0,0 +1,24 @@ +package client + +import ( + "context" + "errors" + + "github.com/context-labs/whip/internal/protocol" +) + +func (c *Client) Query(ctx context.Context, params protocol.QueryParams) (protocol.QueryResult, error) { + var result protocol.QueryResult + err := c.Call(ctx, "query", params, &result) + if err == nil && result.Content != nil { + if result.RootID != params.RootID { + return protocol.QueryResult{}, errors.New("query content root does not match request") + } + command := protocol.CommandResult{Content: result.Content, Operation: params.Operation} + if err := c.commandContent(ctx, result.RootID, &command); err != nil { + return protocol.QueryResult{}, err + } + result.Result = command.Result + } + return result, err +} diff --git a/internal/daemon/root_cancel_target_test.go b/internal/client/root_cancel_target_test.go similarity index 83% rename from internal/daemon/root_cancel_target_test.go rename to internal/client/root_cancel_target_test.go index e3633e3b4..9a6ca5bf6 100644 --- a/internal/daemon/root_cancel_target_test.go +++ b/internal/client/root_cancel_target_test.go @@ -1,29 +1,31 @@ -package daemon +package client import ( "context" "encoding/json" "testing" + + "github.com/context-labs/whip/internal/protocol" ) type blockedSubmissionConnection struct { *staticRootConnection - entered chan CommandParams + entered chan protocol.CommandParams release chan struct{} } -func (c *blockedSubmissionConnection) Command(ctx context.Context, p CommandParams) (CommandResult, error) { +func (c *blockedSubmissionConnection) Command(ctx context.Context, p protocol.CommandParams) (protocol.CommandResult, error) { c.entered <- p select { case <-ctx.Done(): - return CommandResult{Status: "queued"}, ctx.Err() + return protocol.CommandResult{Status: "queued"}, ctx.Err() case <-c.release: - return CommandResult{Status: "succeeded"}, nil + return protocol.CommandResult{Status: "succeeded"}, nil } } func TestRootCancellationTargetsSubmittedCommandBeforeTurnEvent(t *testing.T) { - connection := &blockedSubmissionConnection{staticRootConnection: newStaticRootConnection(), entered: make(chan CommandParams, 2), release: make(chan struct{})} + connection := &blockedSubmissionConnection{staticRootConnection: newStaticRootConnection(), entered: make(chan protocol.CommandParams, 2), release: make(chan struct{})} client := &RootClient{clientID: "client", instanceID: "test", rootID: "root", state: RootLive, conn: connection, activeTurns: map[string]string{"root": "stale-turn"}} action, err := client.NewAction("submit", map[string]string{"text": "hello"}) if err != nil { diff --git a/internal/daemon/root_client.go b/internal/client/root_client.go similarity index 85% rename from internal/daemon/root_client.go rename to internal/client/root_client.go index 010bec6cf..8c180e5d8 100644 --- a/internal/daemon/root_client.go +++ b/internal/client/root_client.go @@ -1,4 +1,4 @@ -package daemon +package client import ( "context" @@ -12,6 +12,7 @@ import ( "sync/atomic" "time" + "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -46,11 +47,11 @@ func (s RootClientState) String() string { // RootConnection is the protocol surface used by RootClient. The interface // keeps command-line and protocol-adapter tests independent of a real socket. type RootConnection interface { - Command(context.Context, CommandParams) (CommandResult, error) - Replay(context.Context, ReplayParams) (ReplayResult, error) + Command(context.Context, protocol.CommandParams) (protocol.CommandResult, error) + Replay(context.Context, protocol.ReplayParams) (protocol.ReplayResult, error) Snapshot(context.Context, string) (session.RootSnapshot, error) - Subscribe(context.Context, string, int64) (SubscribeResult, error) - Events() <-chan ProtocolEvent + Subscribe(context.Context, string, int64) (protocol.SubscribeResult, error) + Events() <-chan protocol.ProtocolEvent Done() <-chan struct{} Err() error Close() error @@ -72,7 +73,7 @@ type RootUpdate struct { State RootClientState StateChanged bool Snapshot *session.RootSnapshot - Event *ProtocolEvent + Event *protocol.ProtocolEvent Err error } @@ -80,7 +81,7 @@ type RootUpdate struct { type RootClientOptions struct { ClientID string RootID string - Create *CreateSession + Create *session.CreateSession // DeferCreate connects host services first; StartSession admits the template. DeferCreate bool Connector RootConnector @@ -93,7 +94,7 @@ type RootClientOptions struct { type RootClient struct { clientID string instanceID string - create *CreateSession + create *session.CreateSession deferCreate bool connect RootConnector retryMin time.Duration @@ -149,7 +150,7 @@ func NewRootClient(options RootClientOptions) (*RootClient, error) { rootID: options.RootID, create: options.Create, deferCreate: options.DeferCreate, connect: options.Connector, retryMin: options.RetryMin, retryMax: options.RetryMax, ctx: ctx, cancel: cancel, done: make(chan struct{}), changed: make(chan struct{}), - updates: make(chan RootUpdate, MaxOutboundEnvelopes), + updates: make(chan RootUpdate, daemonconn.MaxOutboundEnvelopes), }, nil } @@ -288,9 +289,9 @@ func (c *RootClient) NewAction(operation string, payload any) (RootAction, error }, nil } -func (c *RootClient) Command(ctx context.Context, action RootAction) (CommandResult, error) { +func (c *RootClient) Command(ctx context.Context, action RootAction) (protocol.CommandResult, error) { if action.CommandID == "" || action.Operation == "" || action.RootID == "" { - return CommandResult{}, errors.New("action identity and operation are required") + return protocol.CommandResult{}, errors.New("action identity and operation are required") } tracked := false for { @@ -299,13 +300,13 @@ func (c *RootClient) Command(ctx context.Context, action RootAction) (CommandRes c.mu.RUnlock() if state != RootLive || connection == nil { if !c.started.Load() { - return CommandResult{}, fmt.Errorf("commands are disabled while client is %s", state) + return protocol.CommandResult{}, fmt.Errorf("commands are disabled while client is %s", state) } if !c.waitForLive(ctx) { if err := ctx.Err(); err != nil { - return CommandResult{}, err + return protocol.CommandResult{}, err } - return CommandResult{}, c.ctx.Err() + return protocol.CommandResult{}, c.ctx.Err() } continue } @@ -318,7 +319,7 @@ func (c *RootClient) Command(ctx context.Context, action RootAction) (CommandRes tracked = true c.mu.Unlock() } - result, err := connection.Command(ctx, CommandParams{ + result, err := connection.Command(ctx, protocol.CommandParams{ CommandID: action.CommandID, Scope: string(session.CommandScopeRoot), RootID: action.RootID, Operation: action.Operation, Payload: action.Payload, }) @@ -336,22 +337,22 @@ func (c *RootClient) Command(ctx context.Context, action RootAction) (CommandRes return result, err } if ctx.Err() != nil { - return CommandResult{}, ctx.Err() + return protocol.CommandResult{}, ctx.Err() } select { case <-connection.Done(): continue default: - return CommandResult{}, err + return protocol.CommandResult{}, err } } } // ValidateProvider performs an ephemeral daemon request. Unlike Command, its // credential-bearing payload is never admitted to the durable command log. -func (c *RootClient) ValidateProvider(ctx context.Context, params ProviderValidateParams) (ProviderValidateResult, error) { +func (c *RootClient) ValidateProvider(ctx context.Context, params protocol.ProviderValidateParams) (protocol.ProviderValidateResult, error) { type validator interface { - ValidateProvider(context.Context, ProviderValidateParams) (ProviderValidateResult, error) + ValidateProvider(context.Context, protocol.ProviderValidateParams) (protocol.ProviderValidateResult, error) } for { c.mu.RLock() @@ -360,35 +361,35 @@ func (c *RootClient) ValidateProvider(ctx context.Context, params ProviderValida if state != RootLive || connection == nil { if !c.started.Load() || !c.waitForLive(ctx) { if err := ctx.Err(); err != nil { - return ProviderValidateResult{}, err + return protocol.ProviderValidateResult{}, err } - return ProviderValidateResult{}, c.ctx.Err() + return protocol.ProviderValidateResult{}, c.ctx.Err() } continue } provider, ok := connection.(validator) if !ok { - return ProviderValidateResult{}, errors.New("daemon connection does not support provider validation") + return protocol.ProviderValidateResult{}, errors.New("daemon connection does not support provider validation") } result, err := provider.ValidateProvider(ctx, params) if err == nil { return result, nil } if ctx.Err() != nil { - return ProviderValidateResult{}, ctx.Err() + return protocol.ProviderValidateResult{}, ctx.Err() } select { case <-connection.Done(): continue default: - return ProviderValidateResult{}, err + return protocol.ProviderValidateResult{}, err } } } -func (c *RootClient) DecidePermission(ctx context.Context, action RootAction, permissionID string, allow bool, reason, remember string) (PermissionDecisionResult, error) { +func (c *RootClient) DecidePermission(ctx context.Context, action RootAction, permissionID string, allow bool, reason, remember string) (protocol.PermissionDecisionResult, error) { if action.CommandID == "" || action.Operation != "permission.decide" || action.RootID == "" || permissionID == "" { - return PermissionDecisionResult{}, errors.New("permission action requires stable command and permission identities") + return protocol.PermissionDecisionResult{}, errors.New("permission action requires stable command and permission identities") } for { c.mu.RLock() @@ -397,40 +398,40 @@ func (c *RootClient) DecidePermission(ctx context.Context, action RootAction, pe if state != RootLive || connection == nil { if !c.waitForLive(ctx) { if err := ctx.Err(); err != nil { - return PermissionDecisionResult{}, err + return protocol.PermissionDecisionResult{}, err } - return PermissionDecisionResult{}, c.ctx.Err() + return protocol.PermissionDecisionResult{}, c.ctx.Err() } continue } approver, ok := connection.(interface { - DecidePermission(context.Context, PermissionDecision) (PermissionDecisionResult, error) + DecidePermission(context.Context, protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) }) if !ok { - return PermissionDecisionResult{}, errors.New("daemon connection cannot approve permissions") + return protocol.PermissionDecisionResult{}, errors.New("daemon connection cannot approve permissions") } - result, err := approver.DecidePermission(ctx, PermissionDecision{ + result, err := approver.DecidePermission(ctx, protocol.PermissionDecision{ CommandID: action.CommandID, RootID: action.RootID, PermissionID: permissionID, Allow: allow, Reason: reason, Remember: remember, }) if err == nil { return result, nil } if ctx.Err() != nil { - return PermissionDecisionResult{}, ctx.Err() + return protocol.PermissionDecisionResult{}, ctx.Err() } select { case <-connection.Done(): continue default: - return PermissionDecisionResult{}, err + return protocol.PermissionDecisionResult{}, err } } } // SetPermissionMode changes prompting behavior through the durable command path. -func (c *RootClient) SetPermissionMode(ctx context.Context, action RootAction) (CommandResult, error) { +func (c *RootClient) SetPermissionMode(ctx context.Context, action RootAction) (protocol.CommandResult, error) { if action.CommandID == "" || action.Operation != "permission.mode" || action.RootID == "" { - return CommandResult{}, errors.New("permission mode requires stable command and root identities") + return protocol.CommandResult{}, errors.New("permission mode requires stable command and root identities") } return c.Command(ctx, action) } @@ -493,7 +494,7 @@ func (c *RootClient) run() { connection, err := c.connect(c.ctx, cursors) if err != nil { c.transition(RootDisconnected, err) - if failure, ok := errors.AsType[*RPCError](err); ok && failure.Code != -32002 && failure.Code != -32004 { + if failure, ok := errors.AsType[*protocol.RPCError](err); ok && failure.Code != -32002 && failure.Code != -32004 { return } if !c.retry(delay) { @@ -534,7 +535,9 @@ func (c *RootClient) synchronize(connection RootConnection) error { c.mu.Lock() deferred := c.deferCreate if !deferred && c.create != nil && c.create.ExecutionEngine == "" { - if initialized, ok := connection.(interface{ InitializeResult() InitializeResult }); ok { + if initialized, ok := connection.(interface { + InitializeResult() protocol.InitializeResult + }); ok { c.create.ExecutionEngine = initialized.InitializeResult().DefaultExecutionEngine } if c.create.ExecutionEngine == "" { @@ -550,7 +553,7 @@ func (c *RootClient) synchronize(connection RootConnection) error { if err != nil { return err } - result, err := connection.Command(c.ctx, CommandParams{ + result, err := connection.Command(c.ctx, protocol.CommandParams{ CommandID: c.clientID + "-session-" + c.instanceID, Scope: string(session.CommandScopeDaemon), Operation: "session.create", Payload: payload, }) @@ -568,7 +571,7 @@ func (c *RootClient) synchronize(connection RootConnection) error { c.transition(RootSnapshotting, nil) if cursor > 0 { - replay, err := connection.Replay(c.ctx, ReplayParams{RootID: rootID, Cursor: cursor}) + replay, err := connection.Replay(c.ctx, protocol.ReplayParams{RootID: rootID, Cursor: cursor}) if err != nil { return err } @@ -625,7 +628,7 @@ func (c *RootClient) consume(connection RootConnection) bool { } } -func (c *RootClient) emitEvent(event ProtocolEvent) bool { +func (c *RootClient) emitEvent(event protocol.ProtocolEvent) bool { c.mu.Lock() if (event.SubscriptionID != "" && event.SubscriptionID != c.subscriptionID) || event.RootID != c.rootID || event.Seq <= c.cursor { c.mu.Unlock() diff --git a/internal/client/root_client_services_behavior_test.go b/internal/client/root_client_services_behavior_test.go new file mode 100644 index 000000000..5c412ddbb --- /dev/null +++ b/internal/client/root_client_services_behavior_test.go @@ -0,0 +1,70 @@ +package client + +import ( + "context" + "errors" + "net" + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/context-labs/whip/internal/protocol" +) + +type lostProviderReply struct { + *staticRootConnection + calls *atomic.Int32 +} + +func (c *lostProviderReply) Call(context.Context, string, any, any) error { + c.calls.Add(1) + _ = c.Close() + return net.ErrClosed +} + +func TestRootClientProviderMutationsAreNotReplayedAfterLostReply(t *testing.T) { + var calls atomic.Int32 + client, err := NewRootClient(RootClientOptions{ClientID: "ephemeral", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, Connector: func(context.Context, map[string]int64) (RootConnection, error) { + return &lostProviderReply{staticRootConnection: newStaticRootConnection(), calls: &calls}, nil + }}) + if err != nil { + t.Fatal(err) + } + client.Start() + defer client.Close() + ctx, cancel := context.WithTimeout(t.Context(), time.Second) + defer cancel() + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + if _, err := client.SetProviderKey(ctx, ProviderKeySetup{Revision: "expected", Provider: "openrouter", Key: "ephemeral-secret"}); !errors.Is(err, net.ErrClosed) { + t.Fatalf("lost reply=%v", err) + } + if calls.Load() != 1 { + t.Fatalf("credential mutation replayed %d times", calls.Load()) + } +} + +func TestRootClientRejectsUnsupportedConnectionServices(t *testing.T) { + client, err := NewRootClient(RootClientOptions{ClientID: "limited", RootID: "root", Connector: func(context.Context, map[string]int64) (RootConnection, error) { return newStaticRootConnection(), nil }}) + if err != nil { + t.Fatal(err) + } + client.Start() + defer client.Close() + ctx, cancel := context.WithTimeout(t.Context(), time.Second) + defer cancel() + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + if _, err := client.ReadConfiguration(ctx); err == nil || !strings.Contains(err.Error(), "does not support") { + t.Fatalf("unsupported provider service=%v", err) + } + if _, err := client.ValidateProvider(ctx, protocol.ProviderValidateParams{}); err == nil || !strings.Contains(err.Error(), "does not support") { + t.Fatalf("unsupported validation=%v", err) + } + if _, err := client.HistoryPage(ctx, protocol.HistoryPageParams{}); err == nil || !strings.Contains(err.Error(), "does not support") { + t.Fatalf("unsupported history=%v", err) + } +} diff --git a/internal/client/root_client_test.go b/internal/client/root_client_test.go new file mode 100644 index 000000000..0794757c9 --- /dev/null +++ b/internal/client/root_client_test.go @@ -0,0 +1,661 @@ +package client + +import ( + "context" + "encoding/json" + "errors" + "net" + "sync" + "testing" + "time" + + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +type deferredRootConnection struct { + *staticRootConnection + commands chan protocol.CommandParams + loseReply bool +} + +func (c *deferredRootConnection) Call(_ context.Context, method string, _, result any) error { + if method != "provider.list" { + return errors.New("unexpected host RPC") + } + *result.(*protocol.ProviderList) = protocol.ProviderList{Selection: &protocol.ProviderSelection{Ready: false}} + return nil +} + +func (c *deferredRootConnection) Command(_ context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + c.commands <- params + if c.loseReply { + _ = c.Close() + return protocol.CommandResult{}, net.ErrClosed + } + return protocol.CommandResult{Status: "succeeded", Output: "created-root"}, nil +} + +func TestRootClientDeferredSessionUsesHostConnectionAndStableCreate(t *testing.T) { + ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) + defer cancel() + commands := make(chan protocol.CommandParams, 4) + connections := make(chan *deferredRootConnection, 4) + attempt := 0 + client, err := NewRootClient(RootClientOptions{ + ClientID: "onboarding", Create: &session.CreateSession{Kind: session.SessionKindAgent, CWD: "/workspace"}, DeferCreate: true, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + attempt++ + connection := &deferredRootConnection{staticRootConnection: newStaticRootConnection(), commands: commands, loseReply: attempt == 3} + connections <- connection + return connection, nil + }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = client.Close() }) + client.Start() + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + if client.RootID() != "" { + t.Fatal("created a session before a provider was chosen") + } + list, err := client.ListProvidersFor(ctx, "", "") + if err != nil || list.Selection == nil { + t.Fatalf("host inventory: %+v %v", list, err) + } + // Closing and reconnecting while still on the home screen must not create. + first := <-connections + if err := first.Close(); err != nil { + t.Fatal(err) + } + select { + case <-connections: + case <-ctx.Done(): + t.Fatal(ctx.Err()) + } + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + select { + case command := <-commands: + t.Fatalf("early command: %+v", command) + default: + } + if err := client.StartSession("coding-model", "openrouter"); err != nil { + t.Fatal(err) + } + if err := client.StartSession("other-model", "other-provider"); err == nil { + t.Fatal("accepted a second session start") + } + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + if client.RootID() != "created-root" { + t.Fatal("did not attach the created session") + } + a, b := <-commands, <-commands + if a.CommandID != b.CommandID || string(a.Payload) != string(b.Payload) || a.Operation != "session.create" { + t.Fatal("lost acknowledgement changed the create identity or selected route") + } + var create session.CreateSession + if err := json.Unmarshal(b.Payload, &create); err != nil { + t.Fatal(err) + } + if create.Model != "coding-model" || create.Provider != "openrouter" || create.CWD != "/workspace" { + t.Fatalf("wrong session template: %+v", create) + } +} + +func TestRootClientStartSessionDuringConnectionRetirement(t *testing.T) { + client, err := NewRootClient(RootClientOptions{ + ClientID: "retiring", Create: &session.CreateSession{}, DeferCreate: true, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { return nil, net.ErrClosed }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = client.Close() }) + // Retirement clears the connection before publishing the next state. + client.state = RootLive + if err := client.StartSession("model", "provider"); err == nil || !client.deferCreate { + t.Fatal("session was admitted without an active connection") + } +} + +type reconnectServer struct { + mu sync.Mutex + events []protocol.ProtocolEvent + attempts int + ids []string +} + +type reconnectConnection struct { + server *reconnectServer + events chan protocol.ProtocolEvent + done chan struct{} + once sync.Once +} + +func (s *reconnectServer) connect(context.Context, map[string]int64) (RootConnection, error) { + return &reconnectConnection{server: s, events: make(chan protocol.ProtocolEvent, 4), done: make(chan struct{})}, nil +} + +func (c *reconnectConnection) Command(_ context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + c.server.mu.Lock() + c.server.attempts++ + c.server.ids = append(c.server.ids, params.CommandID) + attempt := c.server.attempts + if len(c.server.events) == 0 { + c.server.events = append(c.server.events, protocol.ProtocolEvent{RootID: "root", Seq: 1, Kind: "stream.text", Payload: []byte(`{"text":"one"}`)}) + } + event := c.server.events[0] + c.server.mu.Unlock() + if attempt == 1 { + c.events <- event + _ = c.Close() + return protocol.CommandResult{}, net.ErrClosed + } + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "one"}, nil +} + +func (c *reconnectConnection) Replay(_ context.Context, params protocol.ReplayParams) (protocol.ReplayResult, error) { + c.server.mu.Lock() + defer c.server.mu.Unlock() + result := protocol.ReplayResult{Latest: int64(len(c.server.events))} + for _, event := range c.server.events { + if event.Seq > params.Cursor { + result.Events = append(result.Events, event) + } + } + return result, nil +} + +func (*reconnectConnection) Snapshot(context.Context, string) (session.RootSnapshot, error) { + return session.RootSnapshot{RootID: "root"}, nil +} + +func (c *reconnectConnection) Events() <-chan protocol.ProtocolEvent { return c.events } + +func (c *reconnectConnection) Done() <-chan struct{} { return c.done } + +func (*reconnectConnection) Err() error { return net.ErrClosed } + +func (c *reconnectConnection) Close() error { + c.once.Do(func() { close(c.done) }) + return nil +} + +func TestRootClientReconnectsStableCommandWithoutDuplicateEvent(t *testing.T) { + server := &reconnectServer{} + client, err := NewRootClient(RootClientOptions{ + ClientID: "test", RootID: "root", Connector: server.connect, + RetryMin: time.Millisecond, RetryMax: time.Millisecond, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + t.Cleanup(func() { _ = client.Close() }) + if err := client.WaitLive(t.Context()); err != nil { + t.Fatal(err) + } + action, err := client.NewAction("submit", protocol.SubmitPayload{Text: "go"}) + if err != nil { + t.Fatal(err) + } + result, err := client.Command(t.Context(), action) + if err != nil || result.Output != "one" { + t.Fatalf("command = %+v, %v", result, err) + } + deadline := time.After(time.Second) + events := 0 + for events < 1 { + select { + case update := <-client.Updates(): + if update.Event != nil { + events++ + } + case <-deadline: + t.Fatal("event was not replayed") + } + } + time.Sleep(10 * time.Millisecond) + for { + select { + case update := <-client.Updates(): + if update.Event != nil { + events++ + } + default: + if events != 1 { + t.Fatalf("events = %d, want one", events) + } + server.mu.Lock() + defer server.mu.Unlock() + if server.attempts != 2 || len(server.ids) != 2 || server.ids[0] != server.ids[1] { + t.Fatalf("attempts=%d ids=%v", server.attempts, server.ids) + } + return + } + } +} + +type failingRootConnection struct{ reconnectConnection } + +func (*failingRootConnection) Snapshot(context.Context, string) (session.RootSnapshot, error) { + return session.RootSnapshot{}, errors.New("no session") +} + +func TestRootClientStopsOnPermanentSynchronizationError(t *testing.T) { + client, err := NewRootClient(RootClientOptions{ + ClientID: "test", RootID: "missing", + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + return &failingRootConnection{reconnectConnection{events: make(chan protocol.ProtocolEvent), done: make(chan struct{})}}, nil + }, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + if err := client.WaitLive(t.Context()); err == nil || err.Error() != "no session" { + t.Fatalf("WaitLive error = %v", err) + } + _ = client.Close() +} + +func TestRootClientClosesBeforeStart(t *testing.T) { + client, err := NewRootClient(RootClientOptions{ + ClientID: "client", RootID: "root", + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + t.Fatal("closed client attempted to connect") + return nil, errors.New("unexpected connection") + }, + }) + if err != nil { + t.Fatal(err) + } + if err := client.Close(); err != nil { + t.Fatal(err) + } + client.Start() + select { + case <-client.Updates(): + default: + t.Fatal("updates remained open after close") + } +} + +type staticRootConnection struct { + events chan protocol.ProtocolEvent + done chan struct{} + once sync.Once + commandErr error +} + +func newStaticRootConnection() *staticRootConnection { + return &staticRootConnection{events: make(chan protocol.ProtocolEvent), done: make(chan struct{})} +} + +func (c *staticRootConnection) Command(_ context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + if c.commandErr != nil { + return protocol.CommandResult{}, c.commandErr + } + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "ok"}, nil +} + +func (*staticRootConnection) Replay(context.Context, protocol.ReplayParams) (protocol.ReplayResult, error) { + return protocol.ReplayResult{}, nil +} + +func (*staticRootConnection) Snapshot(_ context.Context, rootID string) (session.RootSnapshot, error) { + return session.RootSnapshot{RootID: rootID}, nil +} + +func (c *staticRootConnection) Events() <-chan protocol.ProtocolEvent { return c.events } + +func (c *staticRootConnection) Done() <-chan struct{} { return c.done } + +func (c *staticRootConnection) Err() error { return c.commandErr } + +func (c *staticRootConnection) Close() error { + c.once.Do(func() { close(c.done) }) + return nil +} + +type permissionRootConnection struct { + *staticRootConnection + decision protocol.PermissionDecision + decide func(protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) +} + +func (c *permissionRootConnection) DecidePermission(_ context.Context, decision protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) { + c.decision = decision + if c.decide != nil { + return c.decide(decision) + } + return protocol.PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil +} + +func TestRootClientValidationAndDisconnectedSurface(t *testing.T) { + for state, want := range map[RootClientState]string{ + RootDisconnected: "disconnected", RootReconnecting: "reconnecting", + RootSnapshotting: "snapshotting", RootLive: "live", RootClientState(99): "unknown", + } { + if got := state.String(); got != want { + t.Errorf("state %d = %q, want %q", state, got, want) + } + } + connector := func(context.Context, map[string]int64) (RootConnection, error) { + return newStaticRootConnection(), nil + } + for _, options := range []RootClientOptions{ + {RootID: "root", Connector: connector}, + {ClientID: "client", Connector: connector}, + {ClientID: "client", RootID: "root", Create: &session.CreateSession{}, Connector: connector}, + } { + if _, err := NewRootClient(options); err == nil { + t.Fatalf("invalid options accepted: %+v", options) + } + } + client, err := NewRootClient(RootClientOptions{ClientID: "client", RootID: "root", Connector: connector}) + if err != nil { + t.Fatal(err) + } + if client.State() != RootDisconnected { + t.Fatalf("initial state = %s", client.State()) + } + if _, err := client.Snapshot(t.Context()); err == nil { + t.Fatal("snapshot should be unavailable before start") + } + if _, err := client.NewAction("", struct{}{}); err == nil { + t.Fatal("empty operation should fail") + } + if _, err := client.NewAction("bad-payload", func() {}); err == nil { + t.Fatal("unmarshalable payload should fail") + } + action, err := client.NewAction("submit", protocol.SubmitPayload{Text: "hello"}) + if err != nil { + t.Fatal(err) + } + if action.RootID != "root" || action.CommandID == "" { + t.Fatalf("action = %+v", action) + } + if _, err := client.Command(t.Context(), RootAction{}); err == nil { + t.Fatal("identity-free command should fail") + } + if _, err := client.Command(t.Context(), action); err == nil { + t.Fatal("command should be disabled before start") + } + permission, err := client.NewAction("permission.decide", struct{}{}) + if err != nil { + t.Fatal(err) + } + if _, err := client.DecidePermission(t.Context(), permission, "", true, "", ""); err == nil { + t.Fatal("permission without an id should fail") + } + mode, err := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) + if err != nil { + t.Fatal(err) + } + if _, err := client.SetPermissionMode(t.Context(), RootAction{}); err == nil { + t.Fatal("identity-free permission mode should fail") + } + if _, err := client.SetPermissionMode(t.Context(), mode); err == nil { + t.Fatal("permission mode should be disabled before start") + } + if err := client.Close(); err != nil { + t.Fatal(err) + } +} + +func TestRootClientProcessInstancesNeverReuseActionOrCreationIDs(t *testing.T) { + connector := func(context.Context, map[string]int64) (RootConnection, error) { + return newStaticRootConnection(), nil + } + first, err := NewRootClient(RootClientOptions{ClientID: "durable", RootID: "root", Connector: connector}) + if err != nil { + t.Fatal(err) + } + second, err := NewRootClient(RootClientOptions{ClientID: "durable", RootID: "root", Connector: connector}) + if err != nil { + t.Fatal(err) + } + firstAction, _ := first.NewAction("submit", protocol.SubmitPayload{Text: "one"}) + secondAction, _ := second.NewAction("submit", protocol.SubmitPayload{Text: "two"}) + if firstAction.CommandID == secondAction.CommandID { + t.Fatalf("separate process instances reused action id %q", firstAction.CommandID) + } + firstCreationID := first.clientID + "-session-" + first.instanceID + secondCreationID := second.clientID + "-session-" + second.instanceID + if firstCreationID == secondCreationID { + t.Fatalf("separate process instances reused session creation id %q", firstCreationID) + } + if first.instanceID == second.instanceID || first.instanceID == "" || second.instanceID == "" { + t.Fatalf("process nonces first=%q second=%q", first.instanceID, second.instanceID) + } + _ = first.Close() + _ = second.Close() +} + +func TestRootClientSwitchRootClosesConnectionAndResynchronizes(t *testing.T) { + first := newStaticRootConnection() + second := newStaticRootConnection() + connections := []*staticRootConnection{first, second} + var calls int + client, err := NewRootClient(RootClientOptions{ + ClientID: "client", RootID: "one", RetryMin: time.Millisecond, RetryMax: time.Millisecond, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + connection := connections[min(calls, len(connections)-1)] + calls++ + return connection, nil + }, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + t.Cleanup(func() { _ = client.Close() }) + if err := client.WaitLive(t.Context()); err != nil { + t.Fatal(err) + } + if err := client.SwitchRoot("two"); err != nil { + t.Fatal(err) + } + if err := client.WaitLive(t.Context()); err != nil { + t.Fatal(err) + } + select { + case <-first.Done(): + default: + t.Fatal("old root connection remained open") + } + if client.RootID() != "two" || client.Cursor() != 0 || calls < 2 { + t.Fatalf("switched root=%q cursor=%d connects=%d", client.RootID(), client.Cursor(), calls) + } +} + +func TestRootClientRetriesAndApprovesWithoutCredentials(t *testing.T) { + connection := &permissionRootConnection{staticRootConnection: newStaticRootConnection()} + attempts := 0 + client, err := NewRootClient(RootClientOptions{ + ClientID: "interactive", RootID: "root", + RetryMin: time.Millisecond, RetryMax: time.Millisecond, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + attempts++ + if attempts == 1 { + return nil, errors.New("daemon starting") + } + return connection, nil + }, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + defer func() { _ = client.Close() }() + if err := client.WaitLive(t.Context()); err != nil { + t.Fatal(err) + } + if attempts != 2 || client.State() != RootLive || client.Cursor() != 0 || client.Err() != nil { + t.Fatalf("attempts=%d state=%s cursor=%d err=%v", attempts, client.State(), client.Cursor(), client.Err()) + } + if snapshot, err := client.Snapshot(t.Context()); err != nil || snapshot.RootID != "root" { + t.Fatalf("snapshot = %+v, %v", snapshot, err) + } + external, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": true}) + if result, err := client.SetPermissionMode(t.Context(), external); err != nil || result.Output != "ok" { + t.Fatalf("external mode = %+v, %v", result, err) + } + automatic, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) + if result, err := client.SetPermissionMode(t.Context(), automatic); err != nil || result.Output != "ok" { + t.Fatalf("automatic mode = %+v, %v", result, err) + } + permission, _ := client.NewAction("permission.decide", struct{}{}) + decision, err := client.DecidePermission(t.Context(), permission, "permission-1", true, "approved", "") + if err != nil || decision.LeaseID != "lease" { + t.Fatalf("permission decision = %+v, %v", decision, err) + } + if connection.decision.PermissionID != "permission-1" || !connection.decision.Allow { + t.Fatalf("permission decision=%+v", connection.decision) + } +} + +func TestRootClientReportsUnsupportedDecisionsAndCommandFailure(t *testing.T) { + connection := newStaticRootConnection() + client, err := NewRootClient(RootClientOptions{ + ClientID: "plain", RootID: "root", + Connector: func(context.Context, map[string]int64) (RootConnection, error) { return connection, nil }, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + defer func() { _ = client.Close() }() + if err := client.WaitLive(t.Context()); err != nil { + t.Fatal(err) + } + permission, _ := client.NewAction("permission.decide", struct{}{}) + if _, err := client.DecidePermission(t.Context(), permission, "permission", true, "", ""); err == nil { + t.Fatal("plain connection should not approve permissions") + } + mode, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) + if _, err := client.SetPermissionMode(t.Context(), mode); err != nil { + t.Fatalf("ordinary command connection should support automatic mode: %v", err) + } + connection.commandErr = errors.New("command rejected") + action, _ := client.NewAction("submit", protocol.SubmitPayload{Text: "hello"}) + if _, err := client.Command(t.Context(), action); !errors.Is(err, connection.commandErr) { + t.Fatalf("command error = %v", err) + } +} + +func (*reconnectConnection) Subscribe(context.Context, string, int64) (protocol.SubscribeResult, error) { + return protocol.SubscribeResult{}, nil +} + +func (*failingRootConnection) Subscribe(context.Context, string, int64) (protocol.SubscribeResult, error) { + return protocol.SubscribeResult{}, nil +} + +func (*staticRootConnection) Subscribe(context.Context, string, int64) (protocol.SubscribeResult, error) { + return protocol.SubscribeResult{}, nil +} + +func TestRootClientRetriesPermissionDecisionWithSameCommandAfterDisconnect(t *testing.T) { + var mu sync.Mutex + decisions := []protocol.PermissionDecision{} + client, err := NewRootClient(RootClientOptions{ + ClientID: "client", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + connection := &permissionRootConnection{staticRootConnection: newStaticRootConnection()} + connection.decide = func(decision protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) { + select { + case <-connection.Done(): + return protocol.PermissionDecisionResult{}, net.ErrClosed + default: + } + mu.Lock() + decisions = append(decisions, decision) + attempt := len(decisions) + mu.Unlock() + if attempt == 1 { + _ = connection.Close() + return protocol.PermissionDecisionResult{}, net.ErrClosed + } + return protocol.PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil + } + return connection, nil + }, + }) + if err != nil { + t.Fatal(err) + } + client.Start() + defer client.Close() + ctx, cancel := context.WithTimeout(t.Context(), time.Second) + defer cancel() + if err := client.WaitLive(ctx); err != nil { + t.Fatal(err) + } + action, err := client.NewAction("permission.decide", struct{}{}) + if err != nil { + t.Fatal(err) + } + result, err := client.DecidePermission(ctx, action, "permission", true, "approved", "tree") + if err != nil || result.OperationID != "operation" { + t.Fatalf("recovered decision = %+v, %v", result, err) + } + mu.Lock() + defer mu.Unlock() + if len(decisions) != 2 || decisions[0] != decisions[1] || decisions[0].CommandID != action.CommandID { + t.Fatalf("permission retry changed its identity or payload: %+v", decisions) + } +} + +type engineCreationConnection struct { + *staticRootConnection + engine string + requests []protocol.CommandParams +} + +func (c *engineCreationConnection) InitializeResult() protocol.InitializeResult { + return protocol.InitializeResult{DefaultExecutionEngine: c.engine} +} + +func (c *engineCreationConnection) Command(_ context.Context, p protocol.CommandParams) (protocol.CommandResult, error) { + c.requests = append(c.requests, p) + return protocol.CommandResult{}, errors.New("lost acknowledgement") +} + +func TestRootClientFreezesDiscoveredEngineAcrossLostAcknowledgement(t *testing.T) { + template := &session.CreateSession{Kind: session.SessionKindAgent, CWD: "/tmp", Model: "m", Provider: "p"} + client, err := NewRootClient(RootClientOptions{ + ClientID: "engine", Create: template, + Connector: func(context.Context, map[string]int64) (RootConnection, error) { + return nil, errors.New("unexpected connection attempt: test synchronizes directly") + }, + }) + if err != nil { + t.Fatal(err) + } + defer client.Close() + first := &engineCreationConnection{staticRootConnection: newStaticRootConnection(), engine: "quickjs"} + if err := client.synchronize(first); err == nil { + t.Fatal("expected lost acknowledgement") + } + template.ExecutionEngine = "starlark" + second := &engineCreationConnection{staticRootConnection: newStaticRootConnection(), engine: "starlark"} + if err := client.synchronize(second); err == nil { + t.Fatal("expected lost acknowledgement") + } + if len(first.requests) != 1 || len(second.requests) != 1 || string(first.requests[0].Payload) != string(second.requests[0].Payload) || first.requests[0].CommandID != second.requests[0].CommandID { + t.Fatal("retried creation changed") + } + var create session.CreateSession + if err := json.Unmarshal(second.requests[0].Payload, &create); err != nil || create.ExecutionEngine != "quickjs" { + t.Fatalf("create=%+v %v", create, err) + } +} diff --git a/internal/client/subscription.go b/internal/client/subscription.go new file mode 100644 index 000000000..1a7208981 --- /dev/null +++ b/internal/client/subscription.go @@ -0,0 +1,45 @@ +package client + +import ( + "context" + "crypto/rand" + + "github.com/context-labs/whip/internal/protocol" +) + +func (c *Client) Subscribe(ctx context.Context, rootID string, cursor int64) (protocol.SubscribeResult, error) { + id := rand.Text() + c.mu.Lock() + previous := c.subscriptions[rootID] + c.subscriptions[rootID] = id + c.mu.Unlock() + if previous != "" { + if err := c.Unsubscribe(ctx, previous); err != nil { + return protocol.SubscribeResult{}, err + } + } + var result protocol.SubscribeResult + err := c.Call(ctx, "events.subscribe", protocol.SubscribeParams{RootID: rootID, SubscriptionID: id, Cursor: cursor}, &result) + if err != nil { + c.mu.Lock() + if c.subscriptions[rootID] == id { + delete(c.subscriptions, rootID) + } + c.mu.Unlock() + } + return result, err +} + +func (c *Client) Unsubscribe(ctx context.Context, id string) error { + if err := c.Call(ctx, "events.unsubscribe", protocol.UnsubscribeParams{SubscriptionID: id}, nil); err != nil { + return err + } + c.mu.Lock() + for root, active := range c.subscriptions { + if active == id { + delete(c.subscriptions, root) + } + } + c.mu.Unlock() + return nil +} diff --git a/internal/client/subscription_lifecycle_test.go b/internal/client/subscription_lifecycle_test.go new file mode 100644 index 000000000..169ce891b --- /dev/null +++ b/internal/client/subscription_lifecycle_test.go @@ -0,0 +1,39 @@ +package client + +import ( + "errors" + "net" + "testing" + + "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/protocoltransport" +) + +func TestClientIgnoresFailureFromReplacedSubscription(t *testing.T) { + serverSide, clientSide := net.Pipe() + defer func() { _ = serverSide.Close(); _ = clientSide.Close() }() + stale, _ := protocoltransport.MarshalFrame(protocoltransport.Message{Method: "subscription.failed", Params: mustJSON(t, protocol.SubscriptionFailure{RootID: "root", SubscriptionID: "old", Error: &protocol.RPCError{Code: -32010, Message: "expired old stream", Data: &protocol.ErrorData{Kind: "resynchronization_required"}}})}) + current, _ := protocoltransport.MarshalFrame(protocoltransport.Message{Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: protocol.ProtocolEvent{RootID: "root", SubscriptionID: "new", Seq: 4, Kind: "turn.started", Payload: []byte(`{}`)}})}) + transport := protocoltransport.NewUnix(clientSide) + written := make(chan struct{}) + go func() { + defer close(written) + defer serverSide.Close() + _, _ = serverSide.Write(append(stale, current...)) + }() + client := &Client{conn: transport, pending: make(map[string]chan callResponse), subscriptions: map[string]string{"root": "new"}, events: make(chan protocol.ProtocolEvent, 2), commandChanged: make(chan struct{}), done: make(chan struct{})} + client.readLoop() + <-written + if _, ok := errors.AsType[*protocol.RPCError](client.Err()); ok { + t.Fatalf("stale failure closed current stream: %v", client.Err()) + } + select { + case event := <-client.Events(): + if event.Seq != 4 { + t.Fatalf("event=%+v", event) + } + default: + t.Fatal("current subscription event lost") + } +} diff --git a/internal/client/transport_test.go b/internal/client/transport_test.go new file mode 100644 index 000000000..1a9148d49 --- /dev/null +++ b/internal/client/transport_test.go @@ -0,0 +1,16 @@ +package client + +import ( + "io" + + "github.com/context-labs/whip/internal/protocoltransport" +) + +func writeProtocolMessage(writer io.Writer, message protocoltransport.Message) error { + frame, err := protocoltransport.MarshalFrame(message) + if err != nil { + return err + } + _, err = writer.Write(frame) + return err +} diff --git a/internal/client/view.go b/internal/client/view.go new file mode 100644 index 000000000..61da09656 --- /dev/null +++ b/internal/client/view.go @@ -0,0 +1,28 @@ +package client + +import ( + "context" + + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" +) + +func (c *Client) HistoryPage(ctx context.Context, params protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) { + var page session.BoundedTranscriptPage + err := c.Call(ctx, "history.page", params, &page) + return page, err +} + +// TracePage reads a root's spans after a cursor; see protocol.TracePageParams. +func (c *Client) TracePage(ctx context.Context, params protocol.TracePageParams) (session.SpanPage, error) { + var page session.SpanPage + err := c.Call(ctx, "trace.page", params, &page) + return page, err +} + +// TraceExport renders a session as OTLP/JSON; see protocol.TraceExportParams. +func (c *Client) TraceExport(ctx context.Context, params protocol.TraceExportParams) (protocol.TraceExportResult, error) { + var result protocol.TraceExportResult + err := c.Call(ctx, "trace.export", params, &result) + return result, err +} diff --git a/internal/daemon/websocket_client.go b/internal/client/websocket_client.go similarity index 84% rename from internal/daemon/websocket_client.go rename to internal/client/websocket_client.go index bf4c01185..be2d7628c 100644 --- a/internal/daemon/websocket_client.go +++ b/internal/client/websocket_client.go @@ -1,16 +1,17 @@ -package daemon +package client import ( "context" "io" "time" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/protocoltransport" "github.com/gobwas/ws" ) // DialWebSocketClient uses the same handlers and contract as the Unix client. -func DialWebSocketClient(ctx context.Context, endpoint string, initialize InitializeParams) (*Client, error) { +func DialWebSocketClient(ctx context.Context, endpoint string, initialize protocol.InitializeParams) (*Client, error) { conn, buffered, _, err := (ws.Dialer{Timeout: 5 * time.Second}).Dial(ctx, endpoint) if err != nil { return nil, err diff --git a/internal/daemon/acceptance_test.go b/internal/daemon/acceptance_test.go index deb5056eb..a4f72ab22 100644 --- a/internal/daemon/acceptance_test.go +++ b/internal/daemon/acceptance_test.go @@ -17,6 +17,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/rlm" @@ -76,12 +77,12 @@ func stopAcceptanceProcess(t *testing.T, process *acceptanceProcess) { } } -func acceptanceClient(t *testing.T, paths daemonconn.RuntimePaths, clientID string, cursors map[string]int64) *Client { +func acceptanceClient(t *testing.T, paths daemonconn.RuntimePaths, clientID string, cursors map[string]int64) *daemonclient.Client { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() for { - client, err := DialClient(ctx, paths, InitializeParams{ + client, err := daemonclient.DialClient(ctx, paths, InitializeParams{ ProtocolMajor: ProtocolMajor, BuildID: "acceptance", ClientID: clientID, ClientKind: "acceptance", Cursors: cursors, }) if err == nil { diff --git a/internal/daemon/architecture_test.go b/internal/daemon/architecture_test.go index 7e083c153..7dd190a2d 100644 --- a/internal/daemon/architecture_test.go +++ b/internal/daemon/architecture_test.go @@ -47,7 +47,7 @@ func productionGoFiles(t *testing.T, directory string) map[string]string { func TestArchitectureKeepsProviderCallsBehindAgentSession(t *testing.T) { root := repositoryRoot(t) - for _, name := range []string{"daemon", "provider"} { + for _, name := range []string{"daemon", "provider", "client"} { for path, body := range productionGoFiles(t, filepath.Join(root, "internal", name)) { if path == filepath.Join(root, "internal", "daemon", "agent_session.go") { continue @@ -101,6 +101,32 @@ func TestArchitectureKeepsConnectionPlumbingIndependentOfDaemon(t *testing.T) { } } +func TestArchitectureSeparatesNativeClientsFromDaemon(t *testing.T) { + root := repositoryRoot(t) + for directory, forbidden := range map[string]string{ + "client": "github.com/context-labs/whip/internal/daemon", + "daemon": "github.com/context-labs/whip/internal/client", + "tui": "github.com/context-labs/whip/internal/daemon", + "acp": "github.com/context-labs/whip/internal/daemon", + } { + for path, body := range productionGoFiles(t, filepath.Join(root, "internal", directory)) { + file, err := parser.ParseFile(token.NewFileSet(), path, body, parser.ImportsOnly) + if err != nil { + t.Fatal(err) + } + for _, imported := range file.Imports { + name, err := strconv.Unquote(imported.Path.Value) + if err != nil { + t.Fatal(err) + } + if name == forbidden { + t.Errorf("native client boundary imports %q: %s", forbidden, path) + } + } + } + } +} + func TestArchitectureKeepsTUIAsDaemonClient(t *testing.T) { root := repositoryRoot(t) for path, body := range productionGoFiles(t, filepath.Join(root, "internal", "tui")) { diff --git a/internal/daemon/autostart_test.go b/internal/daemon/autostart_test.go index 7f5b56086..040e47e9a 100644 --- a/internal/daemon/autostart_test.go +++ b/internal/daemon/autostart_test.go @@ -13,6 +13,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" @@ -43,7 +44,7 @@ func TestEnsureClientStartsDaemonAcrossStaleSocket(t *testing.T) { } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - client, err := EnsureClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "current", ClientID: "client", ClientKind: "test"}, launch) + client, err := daemonclient.EnsureClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "current", ClientID: "client", ClientKind: "test"}, launch) if err != nil { t.Fatal(err) } @@ -59,25 +60,6 @@ func TestEnsureClientStartsDaemonAcrossStaleSocket(t *testing.T) { } } -func TestEnsureClientReportsLaunchAndContextFailures(t *testing.T) { - paths, err := daemonconn.Paths(t.TempDir()) - if err != nil { - t.Fatal(err) - } - launchErr := errors.New("launch failed") - if _, err := EnsureClient(context.Background(), paths, InitializeParams{}, nil); err == nil { - t.Fatal("missing daemon without launcher succeeded") - } - if _, err := EnsureClient(context.Background(), paths, InitializeParams{}, func() error { return launchErr }); !errors.Is(err, launchErr) { - t.Fatalf("launch failure = %v", err) - } - ctx, cancel := context.WithCancel(context.Background()) - cancel() - if _, err := EnsureClient(ctx, paths, InitializeParams{}, func() error { return daemonconn.ErrDaemonOwned }); !errors.Is(err, context.Canceled) { - t.Fatalf("cancelled autostart = %v", err) - } -} - func TestEnsureClientAttachesAcrossBuildsWithoutRestart(t *testing.T) { home := t.TempDir() paths, err := daemonconn.Paths(home) @@ -92,7 +74,7 @@ func TestEnsureClientAttachesAcrossBuildsWithoutRestart(t *testing.T) { defer running.server.Close() ctx, cancel := context.WithTimeout(t.Context(), time.Second) defer cancel() - client, err := EnsureClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "new", ClientID: "stable", ClientKind: "test"}, func() error { t.Error("responsive daemon triggered a launch"); return nil }) + client, err := daemonclient.EnsureClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "new", ClientID: "stable", ClientKind: "test"}, func() error { t.Error("responsive daemon triggered a launch"); return nil }) if err != nil { t.Fatal(err) } @@ -121,7 +103,7 @@ func TestEnsureClientRejectsOldProtocolWithoutLaunching(t *testing.T) { ctx, cancel := context.WithTimeout(t.Context(), time.Second) defer cancel() for _, major := range []int{1, 2, 3, 4} { - _, err = EnsureClient(ctx, paths, InitializeParams{ + _, err = daemonclient.EnsureClient(ctx, paths, InitializeParams{ ProtocolMajor: major, ClientID: "old", ClientKind: "test", }, func() error { t.Error("protocol mismatch triggered a launch"); return nil }) failure, ok := errors.AsType[*RPCError](err) diff --git a/internal/daemon/collection.go b/internal/daemon/collection.go index e15e48a4c..65d0eb3ef 100644 --- a/internal/daemon/collection.go +++ b/internal/daemon/collection.go @@ -13,24 +13,6 @@ func (s *Server) rootCollection(ctx context.Context, params protocol.RootCollect }) } -func (c *Client) RootCollection(ctx context.Context, params protocol.RootCollectionParams) (session.RootCollectionPage, error) { - var page session.RootCollectionPage - err := c.Call(ctx, "root.collection", params, &page) - return page, err -} - func (s *Server) sessionCatalog(ctx context.Context, params protocol.SessionCatalogParams) (session.SessionCatalogPage, error) { return s.daemon.store.SessionCatalog(ctx, session.CatalogPageOptions{Cursor: params.Cursor, Limit: params.Limit, MaxBytes: params.MaxBytes, Search: params.Search, Status: params.Status}) } - -func (c *Client) SessionCatalog(ctx context.Context, params protocol.SessionCatalogParams) (session.SessionCatalogPage, error) { - var page session.SessionCatalogPage - err := c.Call(ctx, "sessions.list", params, &page) - return page, err -} - -func (c *Client) SessionCatalogRevision(ctx context.Context) (session.CatalogRevision, error) { - var revision session.CatalogRevision - err := c.Call(ctx, "sessions.revision", protocol.EmptyParams{}, &revision) - return revision, err -} diff --git a/internal/daemon/command_outcome.go b/internal/daemon/command_outcome.go index d611524ac..be2affd9e 100644 --- a/internal/daemon/command_outcome.go +++ b/internal/daemon/command_outcome.go @@ -3,7 +3,6 @@ package daemon import ( "encoding/json" - "github.com/context-labs/whip/internal/commandpresentation" "github.com/context-labs/whip/internal/protocol" ) @@ -53,10 +52,3 @@ func encodeTurnOutcome(text string, output json.RawMessage, failure error) []byt } return body } - -func fillCommandPresentation(result *CommandResult) { - result.Output, result.Error = commandpresentation.Decode(result.Operation, result.Result, result.Status) - if result.Failure != nil { - result.Error = result.Failure.Message - } -} diff --git a/internal/daemon/command_outcome_test.go b/internal/daemon/command_outcome_test.go deleted file mode 100644 index 778c3798a..000000000 --- a/internal/daemon/command_outcome_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package daemon - -import "testing" - -func TestFillCommandPresentation(t *testing.T) { - t.Parallel() - for _, test := range []struct { - name string - result CommandResult - output, failure string - }{ - {name: "retains output with explicit failure", result: CommandResult{Operation: "submit", Result: []byte(`{"text":"answer"}`), Failure: &RPCError{Message: "failure"}}, output: "answer", failure: "failure"}, - {name: "empty explicit failure overrides decode error", result: CommandResult{Operation: "submit", Result: []byte(`{`), Failure: &RPCError{}}}, - {name: "nil explicit failure retains decode error", result: CommandResult{Operation: "submit", Result: []byte(`{`)}, failure: "invalid command result"}, - {name: "empty body clears stale presentation", result: CommandResult{Operation: "submit", Output: "stale", Error: "stale"}}, - } { - t.Run(test.name, func(t *testing.T) { - t.Parallel() - fillCommandPresentation(&test.result) - if test.result.Output != test.output || test.result.Error != test.failure { - t.Fatalf("presentation = (%q, %q), want (%q, %q)", test.result.Output, test.result.Error, test.output, test.failure) - } - }) - } -} diff --git a/internal/daemon/completion_client.go b/internal/daemon/completion_client.go deleted file mode 100644 index 5482416a1..000000000 --- a/internal/daemon/completion_client.go +++ /dev/null @@ -1,15 +0,0 @@ -package daemon - -import "context" - -func (c *Client) CompleteWorkspace(ctx context.Context, p CompletionParams) (CompletionResult, error) { - var result CompletionResult - err := c.Call(ctx, "workspace.complete", p, &result) - return result, err -} - -func (c *RootClient) CompleteWorkspace(ctx context.Context, p CompletionParams) (CompletionResult, error) { - var result CompletionResult - err := c.providerCall(ctx, "workspace.complete", p, &result) - return result, err -} diff --git a/internal/daemon/gateway_ownership_test.go b/internal/daemon/gateway_ownership_test.go index 4fcf11750..21efeb250 100644 --- a/internal/daemon/gateway_ownership_test.go +++ b/internal/daemon/gateway_ownership_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/protocol" ) @@ -17,9 +18,9 @@ func TestGatewayPreservesConnectionAndProviderOwnership(t *testing.T) { f := newV2Fixture(t, &fakeRunner{}) ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() - connect := func() *Client { + connect := func() *daemonclient.Client { t.Helper() - client, err := DialWebSocketClient(ctx, f.endpoint, InitializeParams{ + client, err := daemonclient.DialWebSocketClient(ctx, f.endpoint, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientID: "same-browser-id", ClientKind: "desktop", Capabilities: []string{"desktop-browser-v1", "events"}, }) diff --git a/internal/daemon/gateway_test.go b/internal/daemon/gateway_test.go index b97988696..0bea5c445 100644 --- a/internal/daemon/gateway_test.go +++ b/internal/daemon/gateway_test.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "testing" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/webgateway" @@ -17,7 +18,7 @@ func startTestGateway(t *testing.T, paths daemonconn.RuntimePaths, options webga } options.SocketPath = paths.Socket options.Open = func(ctx context.Context) (webgateway.Client, error) { - return DialClient(ctx, paths, InitializeParams{ + return daemonclient.DialClient(ctx, paths, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientKind: "gateway", ClientID: "gateway-" + rand.Text(), Capabilities: []string{protocol.NetworkClientCapability}, }) diff --git a/internal/daemon/identity_test.go b/internal/daemon/identity_test.go index 3f9fe7543..bdcec16a4 100644 --- a/internal/daemon/identity_test.go +++ b/internal/daemon/identity_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -269,11 +270,11 @@ func TestRootSnapshotIsACompleteAuthoritativeClientView(t *testing.T) { } } -func pipeClient(t *testing.T, server *Server, initialize InitializeParams) *Client { +func pipeClient(t *testing.T, server *Server, initialize InitializeParams) *daemonclient.Client { t.Helper() serverConn, clientConn := net.Pipe() go server.serveConn(serverConn) - client, err := NewClient(context.Background(), clientConn, initialize) + client, err := daemonclient.NewClient(context.Background(), clientConn, initialize) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/invoke.go b/internal/daemon/invoke.go index 04d228cb1..fce09cee0 100644 --- a/internal/daemon/invoke.go +++ b/internal/daemon/invoke.go @@ -31,9 +31,3 @@ func (s *Server) invoke(ctx context.Context, params protocol.QueryParams) (proto } return protocol.QueryResult{Result: encodeCommandOutcome(params.Operation, output, nil)}, nil } - -func (c *Client) Invoke(ctx context.Context, params protocol.QueryParams) (protocol.QueryResult, error) { - var result protocol.QueryResult - err := c.Call(ctx, "operation.invoke", params, &result) - return result, err -} diff --git a/internal/daemon/mcp_import_service_test.go b/internal/daemon/mcp_import_service_test.go index 3fe612b14..2bf8b83d9 100644 --- a/internal/daemon/mcp_import_service_test.go +++ b/internal/daemon/mcp_import_service_test.go @@ -20,6 +20,7 @@ import ( "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" "github.com/context-labs/whip/internal/session" ) @@ -159,7 +160,7 @@ func TestMCPBrandIconsHonourTheHostSwitch(t *testing.T) { } // Off: nothing answered, nothing dialed, and config.get says so. off := false - if _, err := providers.UpdateConfiguration(ConfigurationUpdate{Revision: snapshot.Revision, BrandIcons: &off}); err != nil { + if _, err := providers.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: snapshot.Revision, BrandIcons: &off}); err != nil { t.Fatal(err) } if got, err = service.MCPBrandIcons(protocol.MCPBrandIconsParams{Keys: []string{"figma.com"}}); err != nil || len(got.Icons) != 0 || hits.Load() != 1 { diff --git a/internal/daemon/protocol_edge_test.go b/internal/daemon/protocol_edge_test.go index df5dda107..1c60afc1e 100644 --- a/internal/daemon/protocol_edge_test.go +++ b/internal/daemon/protocol_edge_test.go @@ -1,17 +1,10 @@ package daemon import ( - "bufio" - "context" "encoding/json" "errors" - "net" "strings" "testing" - "time" - - "github.com/context-labs/whip/internal/daemonconn" - "github.com/context-labs/whip/internal/session" ) func TestProtocolCodecRejectsInvalidAndOversizedValues(t *testing.T) { @@ -28,231 +21,6 @@ func TestProtocolCodecRejectsInvalidAndOversizedValues(t *testing.T) { } } -func TestClientValidationAndCancellationPaths(t *testing.T) { - if _, err := NewClient(context.Background(), nil, InitializeParams{}); err == nil { - t.Fatal("nil connection initialized") - } - serverSide, clientSide := net.Pipe() - go func() { - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: ProtocolMajor}}) - _, _ = readProtocolFrame(reader) - _, _ = readProtocolFrame(reader) - <-time.After(50 * time.Millisecond) - _ = serverSide.Close() - }() - client, err := NewClient(context.Background(), clientSide, InitializeParams{ProtocolMajor: ProtocolMajor}) - if err != nil { - t.Fatal(err) - } - if err := client.Call(context.Background(), "", struct{}{}, nil); err == nil { - t.Fatal("empty method was accepted") - } - if err := client.Call(context.Background(), "invalid.params", make(chan int), nil); err == nil { - t.Fatal("unmarshalable call params were accepted") - } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) - defer cancel() - if err := client.Call(ctx, "blocked", struct{}{}, nil); !errors.Is(err, context.DeadlineExceeded) { - t.Fatalf("cancelled call = %v", err) - } - go client.heartbeat(context.Background(), time.Millisecond, 5*time.Millisecond) - select { - case <-client.Done(): - case <-time.After(100 * time.Millisecond): - t.Fatal("failed heartbeat did not close the client") - } - if err := client.Err(); err == nil || !strings.Contains(err.Error(), "daemon heartbeat") { - t.Fatalf("heartbeat error = %v", err) - } - if err := client.Call(context.Background(), "after.close", struct{}{}, nil); err == nil { - t.Fatal("closed client accepted a call") - } - if err := client.RequestRestart(context.Background(), 1); err == nil { - t.Fatal("closed client requested restart") - } - if _, err := client.Upload(context.Background(), UploadBeginParams{Size: 2}, []byte("x")); err == nil { - t.Fatal("upload size mismatch was accepted") - } - for _, decision := range []PermissionDecision{ - {RootID: "root", PermissionID: "permission"}, - {CommandID: "command", PermissionID: "permission"}, - {CommandID: "command", RootID: "root"}, - } { - if _, err := client.DecidePermission(context.Background(), decision); err == nil { - t.Fatalf("incomplete decision identities were accepted: %+v", decision) - } - } - if _, err := client.DecidePermission(context.Background(), PermissionDecision{ - CommandID: "command", RootID: "root", PermissionID: "permission", Allow: true, - }); err == nil { - t.Fatal("closed client accepted a permission decision") - } -} - -func TestClientRejectsBadInitializeAndSnapshotReplies(t *testing.T) { - for _, result := range []rpcMessage{ - {ID: json.RawMessage("1"), Error: rpcFailure(-1, "refused")}, - {ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: 99}}, - {ID: json.RawMessage("1"), Result: "not-an-initialize-result"}, - } { - serverSide, clientSide := net.Pipe() - go func() { - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, result) - _ = serverSide.Close() - }() - if _, err := NewClient(context.Background(), clientSide, InitializeParams{ProtocolMajor: ProtocolMajor}); err == nil { - t.Fatalf("bad initialize reply %+v was accepted", result) - } - } - - for _, result := range []any{session.RootSnapshot{RootID: "other"}, "invalid", struct{}{}} { - serverSide, clientSide := net.Pipe() - go func() { - defer serverSide.Close() - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: ProtocolMajor}}) - frame, _ := readProtocolFrame(reader) - request, _ := decodeFrame(frame) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: request.ID, Result: result}) - }() - client, err := NewClient(t.Context(), clientSide, InitializeParams{ProtocolMajor: ProtocolMajor}) - if err != nil { - t.Fatal(err) - } - if _, err := client.Snapshot(t.Context(), "root"); err == nil { - t.Fatal("inconsistent snapshot accepted") - } - _ = client.Close() - } -} - -func TestClientConnectionAndReadLoopFailures(t *testing.T) { - closedServer, closedClient := net.Pipe() - _ = closedServer.Close() - if _, err := NewClient(context.Background(), closedClient, InitializeParams{}); err == nil { - t.Fatal("client initialized across a closed connection") - } - for name, response := range map[string][]byte{ - "eof": nil, - "invalid frame": []byte("{}\n"), - } { - t.Run(name, func(t *testing.T) { - serverSide, clientSide := net.Pipe() - go func() { - _, _ = readProtocolFrame(bufio.NewReader(serverSide)) - if response != nil { - _, _ = serverSide.Write(response) - } - _ = serverSide.Close() - }() - if _, err := NewClient(context.Background(), clientSide, InitializeParams{}); err == nil { - t.Fatal("client accepted a broken initialization response") - } - }) - } - - frames := map[string]rpcMessage{ - "invalid event": {Method: "event", Params: json.RawMessage(`true`)}, - "event overflow": {Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: ProtocolEvent{RootID: "root", Seq: 2}})}, - "orphan reply": {ID: json.RawMessage("99"), Result: true}, - } - for name, message := range frames { - t.Run(name, func(t *testing.T) { - serverSide, clientSide := net.Pipe() - client := &Client{ - conn: newUnixMessageTransport(clientSide), pending: make(map[string]chan callResponse), - commandChanged: make(chan struct{}), events: make(chan ProtocolEvent, 1), done: make(chan struct{}), - } - if name == "event overflow" { - client.events <- ProtocolEvent{Seq: 1} - } - frame, err := marshalFrame(message) - if err != nil { - t.Fatal(err) - } - written := make(chan struct{}) - go func() { - defer close(written) - defer serverSide.Close() - _, _ = serverSide.Write(frame) - }() - client.readLoop() - <-written - if client.Err() == nil { - t.Fatal("read loop exited without a terminal error") - } - _ = serverSide.Close() - }) - } -} - -func TestClientCallRejectsInvalidResultAndRestartCancellation(t *testing.T) { - serverSide, clientSide := net.Pipe() - go func() { - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: ProtocolMajor}}) - frame, _ := readProtocolFrame(reader) - request, _ := decodeFrame(frame) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: request.ID, Result: "wrong shape"}) - _, _ = readProtocolFrame(reader) - <-time.After(20 * time.Millisecond) - _ = serverSide.Close() - }() - client, err := NewClient(context.Background(), clientSide, InitializeParams{}) - if err != nil { - t.Fatal(err) - } - var result map[string]any - if err := client.Call(context.Background(), "invalid.result", struct{}{}, &result); err == nil { - t.Fatal("invalid call result decoded") - } - ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond) - defer cancel() - if err := client.RequestRestart(ctx, 1); !errors.Is(err, context.DeadlineExceeded) { - t.Fatalf("cancelled restart = %v", err) - } - _ = client.Close() -} - -func TestClientUploadPropagatesEachProtocolFailure(t *testing.T) { - for _, failedMethod := range []string{"upload.begin", "upload.chunk", "upload.finish"} { - t.Run(failedMethod, func(t *testing.T) { - serverSide, clientSide := net.Pipe() - go func() { - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, rpcMessage{ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: ProtocolMajor}}) - for { - frame, err := readProtocolFrame(reader) - if err != nil { - return - } - request, _ := decodeFrame(frame) - if request.Method == failedMethod { - _ = writeProtocolMessage(serverSide, rpcMessage{ID: request.ID, Error: rpcFailure(-1, "stopped")}) - return - } - _ = writeProtocolMessage(serverSide, rpcMessage{ID: request.ID, Result: map[string]bool{"accepted": true}}) - } - }() - client, err := NewClient(context.Background(), clientSide, InitializeParams{}) - if err != nil { - t.Fatal(err) - } - if _, err := client.Upload(context.Background(), UploadBeginParams{UploadID: "upload", Size: 1}, []byte("x")); err == nil { - t.Fatal("upload protocol failure was ignored") - } - _ = client.Close() - }) - } -} - func mustJSON(t *testing.T, value any) json.RawMessage { t.Helper() raw, err := json.Marshal(value) @@ -261,42 +29,3 @@ func mustJSON(t *testing.T, value any) json.RawMessage { } return raw } - -func TestClientPermissionDecisionUsesUnsignedPayload(t *testing.T) { - serverSide, clientSide := net.Pipe() - requests := make(chan rpcMessage, 1) - go func() { - defer serverSide.Close() - reader := bufio.NewReader(serverSide) - _, _ = readProtocolFrame(reader) - _ = writeProtocolMessage(serverSide, rpcMessage{ - ID: json.RawMessage("1"), Result: InitializeResult{ProtocolMajor: ProtocolMajor}, - }) - frame, _ := readProtocolFrame(reader) - request, _ := decodeFrame(frame) - requests <- request - _ = writeProtocolMessage(serverSide, rpcMessage{ - ID: request.ID, Result: PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, - }) - }() - client, err := NewClient(t.Context(), clientSide, InitializeParams{ProtocolMajor: ProtocolMajor}) - if err != nil { - t.Fatal(err) - } - defer client.Close() - decision := PermissionDecision{ - CommandID: "decision-1", RootID: "root", PermissionID: "permission", - Allow: true, Reason: "approved", Remember: "tree", - } - result, err := client.DecidePermission(t.Context(), decision) - if err != nil || result.OperationID != "operation" || result.LeaseID != "lease" { - t.Fatalf("decision = %+v, %v", result, err) - } - request := <-requests - want := mustJSON(t, struct { - Decision PermissionDecision `json:"decision"` - }{Decision: decision}) - if request.Method != "permission.decide" || string(request.Params) != string(want) { - t.Fatalf("decision wire message = %s %s, want permission.decide %s", request.Method, request.Params, want) - } -} diff --git a/internal/daemon/provider_client_behavior_test.go b/internal/daemon/provider_client_behavior_test.go index a1a45cd75..1d1bbca59 100644 --- a/internal/daemon/provider_client_behavior_test.go +++ b/internal/daemon/provider_client_behavior_test.go @@ -12,29 +12,31 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) type providerBehaviorClient interface { - ReadConfiguration(context.Context) (RuntimeConfiguration, error) - UpdateConfiguration(context.Context, ConfigurationUpdate) (RuntimeConfiguration, error) - SetProviderKey(context.Context, ProviderKeySetup) (RuntimeConfiguration, error) - BeginLogin(context.Context) (ProviderLoginStatus, error) - LoginStatus(context.Context, string) (ProviderLoginStatus, error) - CancelLogin(context.Context, string) (ProviderLoginStatus, error) - SelectLoginTeam(context.Context, string, string) (ProviderLoginStatus, error) - SelectLoginProject(context.Context, string, string) (ProviderLoginStatus, error) - CreateLoginProject(context.Context, string, string) (ProviderLoginStatus, error) - ListLogins(context.Context) (ProviderLoginList, error) - ProviderStatus(context.Context, string) (ProviderStatus, error) - LogoutProvider(context.Context, string) (ProviderStatus, error) - RotateProviderKey(context.Context, string) (ProviderStatus, error) + ReadConfiguration(context.Context) (protocol.RuntimeConfiguration, error) + UpdateConfiguration(context.Context, protocol.ConfigurationUpdate) (protocol.RuntimeConfiguration, error) + SetProviderKey(context.Context, protocol.ProviderKeySetup) (protocol.RuntimeConfiguration, error) + BeginLogin(context.Context) (protocol.ProviderLoginStatus, error) + LoginStatus(context.Context, string) (protocol.ProviderLoginStatus, error) + CancelLogin(context.Context, string) (protocol.ProviderLoginStatus, error) + SelectLoginTeam(context.Context, string, string) (protocol.ProviderLoginStatus, error) + SelectLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) + CreateLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) + ListLogins(context.Context) (protocol.ProviderLoginList, error) + ProviderStatus(context.Context, string) (protocol.ProviderStatus, error) + LogoutProvider(context.Context, string) (protocol.ProviderStatus, error) + RotateProviderKey(context.Context, string) (protocol.ProviderStatus, error) } -func providerBehaviorFixture(t *testing.T) (*Server, *Client, *RootClient, string) { +func providerBehaviorFixture(t *testing.T) (*Server, *daemonclient.Client, *daemonclient.RootClient, string) { t.Helper() t.Setenv("WHIPCODE_HOME", t.TempDir()) store := openStore(t, filepath.Join(t.TempDir(), "sessions.db")) @@ -55,7 +57,7 @@ func providerBehaviorFixture(t *testing.T) (*Server, *Client, *RootClient, strin t.Error(err) } }) - root, err := NewRootClient(RootClientOptions{ClientID: "provider-behavior", RootID: rootID, Connector: func(context.Context, map[string]int64) (RootConnection, error) { return client, nil }}) + root, err := daemonclient.NewRootClient(daemonclient.RootClientOptions{ClientID: "provider-behavior", RootID: rootID, Connector: func(context.Context, map[string]int64) (daemonclient.RootConnection, error) { return client, nil }}) if err != nil { t.Fatal(err) } @@ -89,7 +91,7 @@ func TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts(t *tes ID: "kuzco", Name: "Kuzco", URL: "ws://kuzco.test/api/v3/ws", RuntimeID: "remote-runtime", ConnectOnLaunch: true, }} - after, err := client.UpdateConfiguration(t.Context(), ConfigurationUpdate{Revision: before.Revision, RemoteHosts: &hosts}) + after, err := client.UpdateConfiguration(t.Context(), protocol.ConfigurationUpdate{Revision: before.Revision, RemoteHosts: &hosts}) if err != nil { t.Fatal(err) } @@ -101,7 +103,7 @@ func TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts(t *tes t.Fatalf("endpoint was not normalized: %+v", *read.RemoteHosts) } empty := []config.RemoteHost{} - if _, err := root.UpdateConfiguration(t.Context(), ConfigurationUpdate{Revision: before.Revision, RemoteHosts: &empty}); err == nil { + if _, err := root.UpdateConfiguration(t.Context(), protocol.ConfigurationUpdate{Revision: before.Revision, RemoteHosts: &empty}); err == nil { t.Fatal("stale browser overwrote host list") } persisted, err := config.Load() @@ -115,7 +117,7 @@ func TestProviderClientRemoteHostsPreserveConfigurationAndRejectConflicts(t *tes if err != nil || strings.Contains(string(encoded), provider.APIKey) { t.Fatalf("config response exposed a credential: %v", err) } - cleared, err := root.UpdateConfiguration(t.Context(), ConfigurationUpdate{Revision: after.Revision, RemoteHosts: &empty}) + cleared, err := root.UpdateConfiguration(t.Context(), protocol.ConfigurationUpdate{Revision: after.Revision, RemoteHosts: &empty}) if err != nil || cleared.RemoteHosts == nil || len(*cleared.RemoteHosts) != 0 { t.Fatalf("cannot remove last profile: %+v %v", cleared, err) } @@ -134,11 +136,11 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if err != nil { t.Fatal(err) } - before, err = api.SetProviderKey(t.Context(), ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: " private-api-key "}) + before, err = api.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: before.Revision, Provider: "openrouter", Key: " private-api-key "}) if err != nil { t.Fatal(err) } - after, err := api.UpdateConfiguration(t.Context(), ConfigurationUpdate{Revision: before.Revision, ImportClaude: new(false), ImportCodex: new(false), DefaultModel: new("fixture-model"), DefaultProvider: new("openrouter"), DefaultEffort: new("high"), CompactModel: new("compact-model"), CompactProvider: new("openrouter"), CompactPercent: new(72), GoalMaxRounds: new(8), MaxRetries: new(2)}) + after, err := api.UpdateConfiguration(t.Context(), protocol.ConfigurationUpdate{Revision: before.Revision, ImportClaude: new(false), ImportCodex: new(false), DefaultModel: new("fixture-model"), DefaultProvider: new("openrouter"), DefaultEffort: new("high"), CompactModel: new("compact-model"), CompactProvider: new("openrouter"), CompactPercent: new(72), GoalMaxRounds: new(8), MaxRetries: new(2)}) if err != nil { t.Fatal(err) } @@ -146,10 +148,10 @@ func TestProviderClientOnboardingPersistsSettingsWithoutJournalingSecrets(t *tes if err != nil || !reflect.DeepEqual(persisted, after) || persisted.ImportClaude || persisted.ImportCodex || persisted.DefaultModel != "fixture-model" || persisted.DefaultEffort != "high" || persisted.CompactPercent != 72 || persisted.GoalMaxRounds != 8 || persisted.MaxRetries != 2 { t.Fatalf("settings did not persist: %+v %v", persisted, err) } - if _, err := api.UpdateConfiguration(t.Context(), ConfigurationUpdate{Revision: before.Revision, MaxRetries: new(99)}); err == nil { + if _, err := api.UpdateConfiguration(t.Context(), protocol.ConfigurationUpdate{Revision: before.Revision, MaxRetries: new(99)}); err == nil { t.Fatal("stale update accepted") } - after, err = api.SetProviderKey(t.Context(), ProviderKeySetup{Revision: after.Revision, Provider: "openrouter", Key: " private-api-key "}) + after, err = api.SetProviderKey(t.Context(), protocol.ProviderKeySetup{Revision: after.Revision, Provider: "openrouter", Key: " private-api-key "}) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/provider_client_configuration_test.go b/internal/daemon/provider_client_configuration_test.go index 514499059..cf765dd91 100644 --- a/internal/daemon/provider_client_configuration_test.go +++ b/internal/daemon/provider_client_configuration_test.go @@ -14,7 +14,7 @@ import ( ) type providerConfigurationClient interface { - ReadConfiguration(context.Context) (RuntimeConfiguration, error) + ReadConfiguration(context.Context) (protocol.RuntimeConfiguration, error) ListProviders(context.Context) (protocol.ProviderList, error) ListProvidersFor(context.Context, string, string) (protocol.ProviderList, error) ProviderCatalogs(context.Context, bool) (protocol.ProviderCatalogsResult, error) @@ -22,7 +22,7 @@ type providerConfigurationClient interface { ReadProvider(context.Context, string) (protocol.ProviderConfiguration, error) CreateProvider(context.Context, protocol.ProviderCreateParams) (protocol.ProviderConfiguration, error) UpdateProvider(context.Context, protocol.ProviderUpdateParams) (protocol.ProviderConfiguration, error) - DisconnectProvider(context.Context, protocol.ProviderDisconnectParams) (ProviderStatus, error) + DisconnectProvider(context.Context, protocol.ProviderDisconnectParams) (protocol.ProviderStatus, error) RemoveProvider(context.Context, protocol.ProviderRemoveParams) (protocol.ProviderRemoveResult, error) } diff --git a/internal/daemon/provider_connections_test.go b/internal/daemon/provider_connections_test.go index 0450a89a8..73a8d5e12 100644 --- a/internal/daemon/provider_connections_test.go +++ b/internal/daemon/provider_connections_test.go @@ -13,6 +13,8 @@ import ( "github.com/context-labs/whip/internal/agent" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" ) @@ -105,7 +107,7 @@ func TestProviderDisableBlocksRetainedRootChildAndHelperClients(t *testing.T) { t.Fatal(err) } disabled := []string{"provider", "helper"} - if _, err := service.UpdateConfiguration(ConfigurationUpdate{Revision: before.Revision, DisabledProviders: &disabled}); err != nil { + if _, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{Revision: before.Revision, DisabledProviders: &disabled}); err != nil { t.Fatal(err) } spawned, err := runtime.rootNode.host.Call(t.Context(), "agents", "spawn", map[string]any{"name": "child", "prompt": "blocked work", "report": "message"}) diff --git a/internal/daemon/provider_integration_test.go b/internal/daemon/provider_integration_test.go index b10f67d52..1724bd69f 100644 --- a/internal/daemon/provider_integration_test.go +++ b/internal/daemon/provider_integration_test.go @@ -15,6 +15,7 @@ import ( "github.com/context-labs/whip/internal/inferencenet" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" ) type providerIntegrationTransport func(*http.Request) (*http.Response, error) @@ -145,13 +146,13 @@ func providerOnboardingHTTPFixture(t *testing.T) { t.Cleanup(inferencenet.SetURLsForTest(endpoint.URL, endpoint.URL, endpoint.URL+"/v1")) } -func waitProviderClientState(t *testing.T, client providerBehaviorClient, id, state string) ProviderLoginStatus { +func waitProviderClientState(t *testing.T, client providerBehaviorClient, id, state string) protocol.ProviderLoginStatus { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) defer cancel() ticker := time.NewTicker(time.Millisecond) defer ticker.Stop() - var result ProviderLoginStatus + var result protocol.ProviderLoginStatus for { var err error result, err = client.LoginStatus(ctx, id) diff --git a/internal/daemon/provider_rpc.go b/internal/daemon/provider_rpc.go index 3abf324ae..27c03864b 100644 --- a/internal/daemon/provider_rpc.go +++ b/internal/daemon/provider_rpc.go @@ -78,7 +78,7 @@ func (s *Server) handleProvider(connection *serverConn, request rpcMessage) (any result, err = s.providers.ReadConfiguration() } case "config.update": - var p ConfigurationUpdate + var p protocol.ConfigurationUpdate if err = decodeProviderParams(request.Params, &p); err == nil { result, err = s.providers.UpdateConfiguration(p) } @@ -98,7 +98,7 @@ func (s *Server) handleProvider(connection *serverConn, request rpcMessage) (any result, err = s.hostMCP.MCPBrandIcons(p) } case "provider.key.set": - var p ProviderKeySetup + var p protocol.ProviderKeySetup if err = decodeProviderParams(request.Params, &p); err == nil { result, err = s.providers.SetProviderKey(connection.ctx, p) } @@ -108,7 +108,7 @@ func (s *Server) handleProvider(connection *serverConn, request rpcMessage) (any result = s.providers.ListLogins() } case "provider.status", "provider.logout", "provider.key.rotate": - var p ProviderNameParams + var p protocol.ProviderNameParams if err = decodeProviderParams(request.Params, &p); err == nil { switch request.Method { case "provider.status": diff --git a/internal/daemon/provider_selection_test.go b/internal/daemon/provider_selection_test.go index e9d5c8221..d38268f4f 100644 --- a/internal/daemon/provider_selection_test.go +++ b/internal/daemon/provider_selection_test.go @@ -6,6 +6,7 @@ import ( "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/protocol" + providersvc "github.com/context-labs/whip/internal/provider" ) @@ -41,7 +42,7 @@ func TestProviderCatalogDefaultPairSurvivesSharedModelsAndRestart(t *testing.T) t.Fatal(err) } model, provider := "shared-catalog-model", "beta" - updated, err := service.UpdateConfiguration(ConfigurationUpdate{ + updated, err := service.UpdateConfiguration(protocol.ConfigurationUpdate{ Revision: revision, DefaultModel: &model, DefaultProvider: &provider, }) if err != nil { diff --git a/internal/daemon/query.go b/internal/daemon/query.go index 9d901e14e..12fcfc042 100644 --- a/internal/daemon/query.go +++ b/internal/daemon/query.go @@ -100,22 +100,6 @@ func (s *Server) query(ctx context.Context, params protocol.QueryParams) (protoc return protocol.QueryResult{RootID: params.RootID, Content: &protocol.ContentHandle{ReferenceID: value.ReferenceID, Digest: value.Digest, Size: value.Size, MediaType: value.MediaType, Source: value.Source}}, nil } -func (c *Client) Query(ctx context.Context, params protocol.QueryParams) (protocol.QueryResult, error) { - var result protocol.QueryResult - err := c.Call(ctx, "query", params, &result) - if err == nil && result.Content != nil { - if result.RootID != params.RootID { - return protocol.QueryResult{}, errors.New("query content root does not match request") - } - command := CommandResult{Content: result.Content, Operation: params.Operation} - if err := c.commandContent(ctx, result.RootID, &command); err != nil { - return protocol.QueryResult{}, err - } - result.Result = command.Result - } - return result, err -} - func queryProviderCatalogs(ctx context.Context, providers *providersvc.ProviderService, payload json.RawMessage) (string, error) { var params protocol.ProviderCatalogParams if len(payload) > 0 { diff --git a/internal/daemon/restart_test.go b/internal/daemon/restart_test.go index 4d1fb2d54..55a040bfe 100644 --- a/internal/daemon/restart_test.go +++ b/internal/daemon/restart_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -87,7 +88,7 @@ func TestRestartReturnsAuthoritativeInterruptedCommandWithoutReexecution(t *test } } -func startTCPClient(t *testing.T, value *Daemon, clientID string) (*Server, *Client, <-chan error) { +func startTCPClient(t *testing.T, value *Daemon, clientID string) (*Server, *daemonclient.Client, <-chan error) { t.Helper() server, err := NewServer(value, ServerOptions{}) if err != nil { @@ -103,7 +104,7 @@ func startTCPClient(t *testing.T, value *Daemon, clientID string) (*Server, *Cli if err != nil { t.Fatal(err) } - client, err := NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: clientID, ClientKind: "test"}) + client, err := daemonclient.NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: clientID, ClientKind: "test"}) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/root_client_services_behavior_test.go b/internal/daemon/root_client_services_behavior_test.go index 358188992..9afef2011 100644 --- a/internal/daemon/root_client_services_behavior_test.go +++ b/internal/daemon/root_client_services_behavior_test.go @@ -5,13 +5,10 @@ import ( "encoding/json" "errors" "fmt" - "net" "os" "path/filepath" "strings" - "sync/atomic" "testing" - "time" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" @@ -86,63 +83,6 @@ func TestRootClientWorkspaceHistoryAndContentRemainScoped(t *testing.T) { } } -type lostProviderReply struct { - *staticRootConnection - calls *atomic.Int32 -} - -func (c *lostProviderReply) Call(context.Context, string, any, any) error { - c.calls.Add(1) - _ = c.Close() - return net.ErrClosed -} - -func TestRootClientProviderMutationsAreNotReplayedAfterLostReply(t *testing.T) { - var calls atomic.Int32 - client, err := NewRootClient(RootClientOptions{ClientID: "ephemeral", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, Connector: func(context.Context, map[string]int64) (RootConnection, error) { - return &lostProviderReply{staticRootConnection: newStaticRootConnection(), calls: &calls}, nil - }}) - if err != nil { - t.Fatal(err) - } - client.Start() - defer client.Close() - ctx, cancel := context.WithTimeout(t.Context(), time.Second) - defer cancel() - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - if _, err := client.SetProviderKey(ctx, ProviderKeySetup{Revision: "expected", Provider: "openrouter", Key: "ephemeral-secret"}); !errors.Is(err, net.ErrClosed) { - t.Fatalf("lost reply=%v", err) - } - if calls.Load() != 1 { - t.Fatalf("credential mutation replayed %d times", calls.Load()) - } -} - -func TestRootClientRejectsUnsupportedConnectionServices(t *testing.T) { - client, err := NewRootClient(RootClientOptions{ClientID: "limited", RootID: "root", Connector: func(context.Context, map[string]int64) (RootConnection, error) { return newStaticRootConnection(), nil }}) - if err != nil { - t.Fatal(err) - } - client.Start() - defer client.Close() - ctx, cancel := context.WithTimeout(t.Context(), time.Second) - defer cancel() - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - if _, err := client.ReadConfiguration(ctx); err == nil || !strings.Contains(err.Error(), "does not support") { - t.Fatalf("unsupported provider service=%v", err) - } - if _, err := client.ValidateProvider(ctx, ProviderValidateParams{}); err == nil || !strings.Contains(err.Error(), "does not support") { - t.Fatalf("unsupported validation=%v", err) - } - if _, err := client.HistoryPage(ctx, HistoryPageParams{}); err == nil || !strings.Contains(err.Error(), "does not support") { - t.Fatalf("unsupported history=%v", err) - } -} - func TestHostServiceRPCRejectsMalformedAndUnscopedReads(t *testing.T) { _, client, _, rootID := providerBehaviorFixture(t) for _, method := range []string{"host.directories.list", "host.attention", "host.themes.resolve", "mailbox.list", "mailbox.read"} { diff --git a/internal/daemon/root_client_test.go b/internal/daemon/root_client_test.go index 1786e7f4c..5d175c66d 100644 --- a/internal/daemon/root_client_test.go +++ b/internal/daemon/root_client_test.go @@ -3,476 +3,16 @@ package daemon import ( "context" "database/sql" - "encoding/json" - "errors" "net" "path/filepath" - "sync" "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) -type deferredRootConnection struct { - *staticRootConnection - commands chan CommandParams - loseReply bool -} - -func (c *deferredRootConnection) Call(_ context.Context, method string, _, result any) error { - if method != "provider.list" { - return errors.New("unexpected host RPC") - } - *result.(*protocol.ProviderList) = protocol.ProviderList{Selection: &protocol.ProviderSelection{Ready: false}} - return nil -} - -func (c *deferredRootConnection) Command(_ context.Context, params CommandParams) (CommandResult, error) { - c.commands <- params - if c.loseReply { - _ = c.Close() - return CommandResult{}, net.ErrClosed - } - return CommandResult{Status: "succeeded", Output: "created-root"}, nil -} - -func TestRootClientDeferredSessionUsesHostConnectionAndStableCreate(t *testing.T) { - ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) - defer cancel() - commands := make(chan CommandParams, 4) - connections := make(chan *deferredRootConnection, 4) - attempt := 0 - client, err := NewRootClient(RootClientOptions{ - ClientID: "onboarding", Create: &CreateSession{Kind: session.SessionKindAgent, CWD: "/workspace"}, DeferCreate: true, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - attempt++ - connection := &deferredRootConnection{staticRootConnection: newStaticRootConnection(), commands: commands, loseReply: attempt == 3} - connections <- connection - return connection, nil - }, - }) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = client.Close() }) - client.Start() - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - if client.RootID() != "" { - t.Fatal("created a session before a provider was chosen") - } - list, err := client.ListProvidersFor(ctx, "", "") - if err != nil || list.Selection == nil { - t.Fatalf("host inventory: %+v %v", list, err) - } - // Closing and reconnecting while still on the home screen must not create. - first := <-connections - if err := first.Close(); err != nil { - t.Fatal(err) - } - select { - case <-connections: - case <-ctx.Done(): - t.Fatal(ctx.Err()) - } - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - select { - case command := <-commands: - t.Fatalf("early command: %+v", command) - default: - } - if err := client.StartSession("coding-model", "openrouter"); err != nil { - t.Fatal(err) - } - if err := client.StartSession("other-model", "other-provider"); err == nil { - t.Fatal("accepted a second session start") - } - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - if client.RootID() != "created-root" { - t.Fatal("did not attach the created session") - } - a, b := <-commands, <-commands - if a.CommandID != b.CommandID || string(a.Payload) != string(b.Payload) || a.Operation != "session.create" { - t.Fatal("lost acknowledgement changed the create identity or selected route") - } - var create CreateSession - if err := json.Unmarshal(b.Payload, &create); err != nil { - t.Fatal(err) - } - if create.Model != "coding-model" || create.Provider != "openrouter" || create.CWD != "/workspace" { - t.Fatalf("wrong session template: %+v", create) - } -} - -func TestRootClientStartSessionDuringConnectionRetirement(t *testing.T) { - client, err := NewRootClient(RootClientOptions{ - ClientID: "retiring", Create: &CreateSession{}, DeferCreate: true, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { return nil, net.ErrClosed }, - }) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = client.Close() }) - // Retirement clears the connection before publishing the next state. - client.state = RootLive - if err := client.StartSession("model", "provider"); err == nil || !client.deferCreate { - t.Fatal("session was admitted without an active connection") - } -} - -type reconnectServer struct { - mu sync.Mutex - events []ProtocolEvent - attempts int - ids []string -} - -type reconnectConnection struct { - server *reconnectServer - events chan ProtocolEvent - done chan struct{} - once sync.Once -} - -func (s *reconnectServer) connect(context.Context, map[string]int64) (RootConnection, error) { - return &reconnectConnection{server: s, events: make(chan ProtocolEvent, 4), done: make(chan struct{})}, nil -} - -func (c *reconnectConnection) Command(_ context.Context, params CommandParams) (CommandResult, error) { - c.server.mu.Lock() - c.server.attempts++ - c.server.ids = append(c.server.ids, params.CommandID) - attempt := c.server.attempts - if len(c.server.events) == 0 { - c.server.events = append(c.server.events, ProtocolEvent{RootID: "root", Seq: 1, Kind: "stream.text", Payload: []byte(`{"text":"one"}`)}) - } - event := c.server.events[0] - c.server.mu.Unlock() - if attempt == 1 { - c.events <- event - _ = c.Close() - return CommandResult{}, net.ErrClosed - } - return CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "one"}, nil -} - -func (c *reconnectConnection) Replay(_ context.Context, params ReplayParams) (ReplayResult, error) { - c.server.mu.Lock() - defer c.server.mu.Unlock() - result := ReplayResult{Latest: int64(len(c.server.events))} - for _, event := range c.server.events { - if event.Seq > params.Cursor { - result.Events = append(result.Events, event) - } - } - return result, nil -} - -func (*reconnectConnection) Snapshot(context.Context, string) (session.RootSnapshot, error) { - return session.RootSnapshot{RootID: "root"}, nil -} -func (c *reconnectConnection) Events() <-chan ProtocolEvent { return c.events } -func (c *reconnectConnection) Done() <-chan struct{} { return c.done } -func (*reconnectConnection) Err() error { return net.ErrClosed } -func (c *reconnectConnection) Close() error { - c.once.Do(func() { close(c.done) }) - return nil -} - -func TestRootClientReconnectsStableCommandWithoutDuplicateEvent(t *testing.T) { - server := &reconnectServer{} - client, err := NewRootClient(RootClientOptions{ - ClientID: "test", RootID: "root", Connector: server.connect, - RetryMin: time.Millisecond, RetryMax: time.Millisecond, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - t.Cleanup(func() { _ = client.Close() }) - if err := client.WaitLive(t.Context()); err != nil { - t.Fatal(err) - } - action, err := client.NewAction("submit", SubmitPayload{Text: "go"}) - if err != nil { - t.Fatal(err) - } - result, err := client.Command(t.Context(), action) - if err != nil || result.Output != "one" { - t.Fatalf("command = %+v, %v", result, err) - } - deadline := time.After(time.Second) - events := 0 - for events < 1 { - select { - case update := <-client.Updates(): - if update.Event != nil { - events++ - } - case <-deadline: - t.Fatal("event was not replayed") - } - } - time.Sleep(10 * time.Millisecond) - for { - select { - case update := <-client.Updates(): - if update.Event != nil { - events++ - } - default: - if events != 1 { - t.Fatalf("events = %d, want one", events) - } - server.mu.Lock() - defer server.mu.Unlock() - if server.attempts != 2 || len(server.ids) != 2 || server.ids[0] != server.ids[1] { - t.Fatalf("attempts=%d ids=%v", server.attempts, server.ids) - } - return - } - } -} - -type failingRootConnection struct{ reconnectConnection } - -func (*failingRootConnection) Snapshot(context.Context, string) (session.RootSnapshot, error) { - return session.RootSnapshot{}, errors.New("no session") -} - -func TestRootClientStopsOnPermanentSynchronizationError(t *testing.T) { - client, err := NewRootClient(RootClientOptions{ - ClientID: "test", RootID: "missing", - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - return &failingRootConnection{reconnectConnection{events: make(chan ProtocolEvent), done: make(chan struct{})}}, nil - }, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - if err := client.WaitLive(t.Context()); err == nil || err.Error() != "no session" { - t.Fatalf("WaitLive error = %v", err) - } - _ = client.Close() -} - -func TestRootClientClosesBeforeStart(t *testing.T) { - client, err := NewRootClient(RootClientOptions{ - ClientID: "client", RootID: "root", - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - t.Fatal("closed client attempted to connect") - return nil, errors.New("unexpected connection") - }, - }) - if err != nil { - t.Fatal(err) - } - if err := client.Close(); err != nil { - t.Fatal(err) - } - client.Start() - select { - case <-client.Updates(): - default: - t.Fatal("updates remained open after close") - } -} - -type staticRootConnection struct { - events chan ProtocolEvent - done chan struct{} - once sync.Once - commandErr error -} - -func newStaticRootConnection() *staticRootConnection { - return &staticRootConnection{events: make(chan ProtocolEvent), done: make(chan struct{})} -} - -func (c *staticRootConnection) Command(_ context.Context, params CommandParams) (CommandResult, error) { - if c.commandErr != nil { - return CommandResult{}, c.commandErr - } - return CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "ok"}, nil -} - -func (*staticRootConnection) Replay(context.Context, ReplayParams) (ReplayResult, error) { - return ReplayResult{}, nil -} - -func (*staticRootConnection) Snapshot(_ context.Context, rootID string) (session.RootSnapshot, error) { - return session.RootSnapshot{RootID: rootID}, nil -} - -func (c *staticRootConnection) Events() <-chan ProtocolEvent { return c.events } -func (c *staticRootConnection) Done() <-chan struct{} { return c.done } -func (c *staticRootConnection) Err() error { return c.commandErr } -func (c *staticRootConnection) Close() error { - c.once.Do(func() { close(c.done) }) - return nil -} - -type permissionRootConnection struct { - *staticRootConnection - decision PermissionDecision - decide func(PermissionDecision) (PermissionDecisionResult, error) -} - -func (c *permissionRootConnection) DecidePermission(_ context.Context, decision PermissionDecision) (PermissionDecisionResult, error) { - c.decision = decision - if c.decide != nil { - return c.decide(decision) - } - return PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil -} - -func TestRootClientValidationAndDisconnectedSurface(t *testing.T) { - for state, want := range map[RootClientState]string{ - RootDisconnected: "disconnected", RootReconnecting: "reconnecting", - RootSnapshotting: "snapshotting", RootLive: "live", RootClientState(99): "unknown", - } { - if got := state.String(); got != want { - t.Errorf("state %d = %q, want %q", state, got, want) - } - } - connector := func(context.Context, map[string]int64) (RootConnection, error) { - return newStaticRootConnection(), nil - } - for _, options := range []RootClientOptions{ - {RootID: "root", Connector: connector}, - {ClientID: "client", Connector: connector}, - {ClientID: "client", RootID: "root", Create: &CreateSession{}, Connector: connector}, - } { - if _, err := NewRootClient(options); err == nil { - t.Fatalf("invalid options accepted: %+v", options) - } - } - client, err := NewRootClient(RootClientOptions{ClientID: "client", RootID: "root", Connector: connector}) - if err != nil { - t.Fatal(err) - } - if client.State() != RootDisconnected { - t.Fatalf("initial state = %s", client.State()) - } - if _, err := client.Snapshot(t.Context()); err == nil { - t.Fatal("snapshot should be unavailable before start") - } - if _, err := client.NewAction("", struct{}{}); err == nil { - t.Fatal("empty operation should fail") - } - if _, err := client.NewAction("bad-payload", func() {}); err == nil { - t.Fatal("unmarshalable payload should fail") - } - action, err := client.NewAction("submit", SubmitPayload{Text: "hello"}) - if err != nil { - t.Fatal(err) - } - if action.RootID != "root" || action.CommandID == "" { - t.Fatalf("action = %+v", action) - } - if _, err := client.Command(t.Context(), RootAction{}); err == nil { - t.Fatal("identity-free command should fail") - } - if _, err := client.Command(t.Context(), action); err == nil { - t.Fatal("command should be disabled before start") - } - permission, err := client.NewAction("permission.decide", struct{}{}) - if err != nil { - t.Fatal(err) - } - if _, err := client.DecidePermission(t.Context(), permission, "", true, "", ""); err == nil { - t.Fatal("permission without an id should fail") - } - mode, err := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) - if err != nil { - t.Fatal(err) - } - if _, err := client.SetPermissionMode(t.Context(), RootAction{}); err == nil { - t.Fatal("identity-free permission mode should fail") - } - if _, err := client.SetPermissionMode(t.Context(), mode); err == nil { - t.Fatal("permission mode should be disabled before start") - } - if err := client.Close(); err != nil { - t.Fatal(err) - } -} - -func TestRootClientProcessInstancesNeverReuseActionOrCreationIDs(t *testing.T) { - connector := func(context.Context, map[string]int64) (RootConnection, error) { - return newStaticRootConnection(), nil - } - first, err := NewRootClient(RootClientOptions{ClientID: "durable", RootID: "root", Connector: connector}) - if err != nil { - t.Fatal(err) - } - second, err := NewRootClient(RootClientOptions{ClientID: "durable", RootID: "root", Connector: connector}) - if err != nil { - t.Fatal(err) - } - firstAction, _ := first.NewAction("submit", SubmitPayload{Text: "one"}) - secondAction, _ := second.NewAction("submit", SubmitPayload{Text: "two"}) - if firstAction.CommandID == secondAction.CommandID { - t.Fatalf("separate process instances reused action id %q", firstAction.CommandID) - } - firstCreationID := first.clientID + "-session-" + first.instanceID - secondCreationID := second.clientID + "-session-" + second.instanceID - if firstCreationID == secondCreationID { - t.Fatalf("separate process instances reused session creation id %q", firstCreationID) - } - if first.instanceID == second.instanceID || first.instanceID == "" || second.instanceID == "" { - t.Fatalf("process nonces first=%q second=%q", first.instanceID, second.instanceID) - } - _ = first.Close() - _ = second.Close() -} - -func TestRootClientSwitchRootClosesConnectionAndResynchronizes(t *testing.T) { - first := newStaticRootConnection() - second := newStaticRootConnection() - connections := []*staticRootConnection{first, second} - var calls int - client, err := NewRootClient(RootClientOptions{ - ClientID: "client", RootID: "one", RetryMin: time.Millisecond, RetryMax: time.Millisecond, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - connection := connections[min(calls, len(connections)-1)] - calls++ - return connection, nil - }, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - t.Cleanup(func() { _ = client.Close() }) - if err := client.WaitLive(t.Context()); err != nil { - t.Fatal(err) - } - if err := client.SwitchRoot("two"); err != nil { - t.Fatal(err) - } - if err := client.WaitLive(t.Context()); err != nil { - t.Fatal(err) - } - select { - case <-first.Done(): - default: - t.Fatal("old root connection remained open") - } - if client.RootID() != "two" || client.Cursor() != 0 || calls < 2 { - t.Fatalf("switched root=%q cursor=%d connects=%d", client.RootID(), client.Cursor(), calls) - } -} - func TestRootClientReceivesEventsAfterExpiredCursorSnapshot(t *testing.T) { databasePath := filepath.Join(t.TempDir(), "sessions.db") store := openStore(t, databasePath) @@ -514,14 +54,14 @@ func TestRootClientReceivesEventsAfterExpiredCursorSnapshot(t *testing.T) { <-served }) - client, err := NewRootClient(RootClientOptions{ + client, err := daemonclient.NewRootClient(daemonclient.RootClientOptions{ ClientID: "expired-cursor", RootID: rootID, RetryMin: time.Millisecond, RetryMax: time.Millisecond, - Connector: func(ctx context.Context, cursors map[string]int64) (RootConnection, error) { + Connector: func(ctx context.Context, cursors map[string]int64) (daemonclient.RootConnection, error) { connection, err := (&net.Dialer{}).DialContext(ctx, "tcp", listener.Addr().String()) if err != nil { return nil, err } - return NewClient(ctx, connection, InitializeParams{ + return daemonclient.NewClient(ctx, connection, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientID: "expired-cursor", ClientKind: "test", Cursors: cursors, }) }, @@ -550,186 +90,3 @@ func TestRootClientReceivesEventsAfterExpiredCursorSnapshot(t *testing.T) { } } } - -func TestRootClientRetriesAndApprovesWithoutCredentials(t *testing.T) { - connection := &permissionRootConnection{staticRootConnection: newStaticRootConnection()} - attempts := 0 - client, err := NewRootClient(RootClientOptions{ - ClientID: "interactive", RootID: "root", - RetryMin: time.Millisecond, RetryMax: time.Millisecond, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - attempts++ - if attempts == 1 { - return nil, errors.New("daemon starting") - } - return connection, nil - }, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - defer func() { _ = client.Close() }() - if err := client.WaitLive(t.Context()); err != nil { - t.Fatal(err) - } - if attempts != 2 || client.State() != RootLive || client.Cursor() != 0 || client.Err() != nil { - t.Fatalf("attempts=%d state=%s cursor=%d err=%v", attempts, client.State(), client.Cursor(), client.Err()) - } - if snapshot, err := client.Snapshot(t.Context()); err != nil || snapshot.RootID != "root" { - t.Fatalf("snapshot = %+v, %v", snapshot, err) - } - external, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": true}) - if result, err := client.SetPermissionMode(t.Context(), external); err != nil || result.Output != "ok" { - t.Fatalf("external mode = %+v, %v", result, err) - } - automatic, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) - if result, err := client.SetPermissionMode(t.Context(), automatic); err != nil || result.Output != "ok" { - t.Fatalf("automatic mode = %+v, %v", result, err) - } - permission, _ := client.NewAction("permission.decide", struct{}{}) - decision, err := client.DecidePermission(t.Context(), permission, "permission-1", true, "approved", "") - if err != nil || decision.LeaseID != "lease" { - t.Fatalf("permission decision = %+v, %v", decision, err) - } - if connection.decision.PermissionID != "permission-1" || !connection.decision.Allow { - t.Fatalf("permission decision=%+v", connection.decision) - } -} - -func TestRootClientReportsUnsupportedDecisionsAndCommandFailure(t *testing.T) { - connection := newStaticRootConnection() - client, err := NewRootClient(RootClientOptions{ - ClientID: "plain", RootID: "root", - Connector: func(context.Context, map[string]int64) (RootConnection, error) { return connection, nil }, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - defer func() { _ = client.Close() }() - if err := client.WaitLive(t.Context()); err != nil { - t.Fatal(err) - } - permission, _ := client.NewAction("permission.decide", struct{}{}) - if _, err := client.DecidePermission(t.Context(), permission, "permission", true, "", ""); err == nil { - t.Fatal("plain connection should not approve permissions") - } - mode, _ := client.NewAction("permission.mode", map[string]bool{"external_permissions": false}) - if _, err := client.SetPermissionMode(t.Context(), mode); err != nil { - t.Fatalf("ordinary command connection should support automatic mode: %v", err) - } - connection.commandErr = errors.New("command rejected") - action, _ := client.NewAction("submit", SubmitPayload{Text: "hello"}) - if _, err := client.Command(t.Context(), action); !errors.Is(err, connection.commandErr) { - t.Fatalf("command error = %v", err) - } -} - -func (*reconnectConnection) Subscribe(context.Context, string, int64) (SubscribeResult, error) { - return SubscribeResult{}, nil -} - -func (*failingRootConnection) Subscribe(context.Context, string, int64) (SubscribeResult, error) { - return SubscribeResult{}, nil -} - -func (*staticRootConnection) Subscribe(context.Context, string, int64) (SubscribeResult, error) { - return SubscribeResult{}, nil -} - -func TestRootClientRetriesPermissionDecisionWithSameCommandAfterDisconnect(t *testing.T) { - var mu sync.Mutex - decisions := []PermissionDecision{} - client, err := NewRootClient(RootClientOptions{ - ClientID: "client", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - connection := &permissionRootConnection{staticRootConnection: newStaticRootConnection()} - connection.decide = func(decision PermissionDecision) (PermissionDecisionResult, error) { - select { - case <-connection.Done(): - return PermissionDecisionResult{}, net.ErrClosed - default: - } - mu.Lock() - decisions = append(decisions, decision) - attempt := len(decisions) - mu.Unlock() - if attempt == 1 { - _ = connection.Close() - return PermissionDecisionResult{}, net.ErrClosed - } - return PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil - } - return connection, nil - }, - }) - if err != nil { - t.Fatal(err) - } - client.Start() - defer client.Close() - ctx, cancel := context.WithTimeout(t.Context(), time.Second) - defer cancel() - if err := client.WaitLive(ctx); err != nil { - t.Fatal(err) - } - action, err := client.NewAction("permission.decide", struct{}{}) - if err != nil { - t.Fatal(err) - } - result, err := client.DecidePermission(ctx, action, "permission", true, "approved", "tree") - if err != nil || result.OperationID != "operation" { - t.Fatalf("recovered decision = %+v, %v", result, err) - } - mu.Lock() - defer mu.Unlock() - if len(decisions) != 2 || decisions[0] != decisions[1] || decisions[0].CommandID != action.CommandID { - t.Fatalf("permission retry changed its identity or payload: %+v", decisions) - } -} - -type engineCreationConnection struct { - *staticRootConnection - engine string - requests []CommandParams -} - -func (c *engineCreationConnection) InitializeResult() InitializeResult { - return InitializeResult{DefaultExecutionEngine: c.engine} -} - -func (c *engineCreationConnection) Command(_ context.Context, p CommandParams) (CommandResult, error) { - c.requests = append(c.requests, p) - return CommandResult{}, errors.New("lost acknowledgement") -} - -func TestRootClientFreezesDiscoveredEngineAcrossLostAcknowledgement(t *testing.T) { - template := &CreateSession{Kind: session.SessionKindAgent, CWD: "/tmp", Model: "m", Provider: "p"} - client, err := NewRootClient(RootClientOptions{ - ClientID: "engine", Create: template, - Connector: func(context.Context, map[string]int64) (RootConnection, error) { - return nil, errors.New("unexpected connection attempt: test synchronizes directly") - }, - }) - if err != nil { - t.Fatal(err) - } - defer client.Close() - first := &engineCreationConnection{staticRootConnection: newStaticRootConnection(), engine: "quickjs"} - if err := client.synchronize(first); err == nil { - t.Fatal("expected lost acknowledgement") - } - template.ExecutionEngine = "starlark" - second := &engineCreationConnection{staticRootConnection: newStaticRootConnection(), engine: "starlark"} - if err := client.synchronize(second); err == nil { - t.Fatal("expected lost acknowledgement") - } - if len(first.requests) != 1 || len(second.requests) != 1 || string(first.requests[0].Payload) != string(second.requests[0].Payload) || first.requests[0].CommandID != second.requests[0].CommandID { - t.Fatal("retried creation changed") - } - var create CreateSession - if err := json.Unmarshal(second.requests[0].Payload, &create); err != nil || create.ExecutionEngine != "quickjs" { - t.Fatalf("create=%+v %v", create, err) - } -} diff --git a/internal/daemon/runtime_parity_test.go b/internal/daemon/runtime_parity_test.go index 65398f35a..b0eaea8ad 100644 --- a/internal/daemon/runtime_parity_test.go +++ b/internal/daemon/runtime_parity_test.go @@ -12,6 +12,7 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/mcp" @@ -153,7 +154,7 @@ func TestRuntimeRegistryEveryOperationOverUnixRPC(t *testing.T) { } } -func runtimeUnixClient(t *testing.T, value *Daemon) *Client { +func runtimeUnixClient(t *testing.T, value *Daemon) *daemonclient.Client { t.Helper() dir, err := os.MkdirTemp("/tmp", "whip-v2-") //nolint:usetesting // short path is required by the Unix socket path-length limit on macOS if err != nil { @@ -174,7 +175,7 @@ func runtimeUnixClient(t *testing.T, value *Daemon) *Client { if err != nil { t.Fatal(err) } - client, err := NewClient(t.Context(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "fixture-client", ClientKind: "test"}) + client, err := daemonclient.NewClient(t.Context(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "fixture-client", ClientKind: "test"}) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/server_gateway_test.go b/internal/daemon/server_gateway_test.go index 8c1e81db1..dcd841e05 100644 --- a/internal/daemon/server_gateway_test.go +++ b/internal/daemon/server_gateway_test.go @@ -9,10 +9,11 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/protocol" ) -func gatewayPolicyClient(t *testing.T, server *Server, directNetwork bool, params InitializeParams) *Client { +func gatewayPolicyClient(t *testing.T, server *Server, directNetwork bool, params InitializeParams) *daemonclient.Client { t.Helper() serverSide, clientSide := net.Pipe() served := make(chan struct{}) @@ -30,7 +31,7 @@ func gatewayPolicyClient(t *testing.T, server *Server, directNetwork bool, param }) ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second) defer cancel() - client, err := NewClient(ctx, clientSide, params) + client, err := daemonclient.NewClient(ctx, clientSide, params) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/server_test.go b/internal/daemon/server_test.go index b8ef6c333..abccc12fa 100644 --- a/internal/daemon/server_test.go +++ b/internal/daemon/server_test.go @@ -18,6 +18,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" @@ -74,7 +75,7 @@ func TestServerServesWithUnresumableSessionAndRecoversAfterRepair(t *testing.T) if err != nil { t.Fatal(err) } - client, err := NewClient(ctx, conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "restore-client", ClientKind: "test"}) + client, err := daemonclient.NewClient(ctx, conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "restore-client", ClientKind: "test"}) if err != nil { t.Fatal(err) } @@ -183,7 +184,7 @@ func TestProtocolClientCommandReplayAndSnapshot(t *testing.T) { if err != nil { t.Fatal(err) } - client, err := NewClient(context.Background(), conn, InitializeParams{ + client, err := daemonclient.NewClient(context.Background(), conn, InitializeParams{ ProtocolMajor: ProtocolMajor, BuildID: "client-build", ClientKind: "test", ClientID: "client-1", Cursors: map[string]int64{rootID: 0}, }) @@ -253,7 +254,7 @@ func TestProtocolAllowsConcurrentPrincipalConnectionsAndRejectsOversizedFrame(t } firstServer, firstClient := net.Pipe() go server.serveConn(firstServer) - first, err := NewClient(context.Background(), firstClient, InitializeParams{ + first, err := daemonclient.NewClient(context.Background(), firstClient, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "duplicate", }) if err != nil { @@ -265,7 +266,7 @@ func TestProtocolAllowsConcurrentPrincipalConnectionsAndRejectsOversizedFrame(t } secondServer, secondClient := net.Pipe() go server.serveConn(secondServer) - second, err := NewClient(context.Background(), secondClient, InitializeParams{ + second, err := daemonclient.NewClient(context.Background(), secondClient, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "duplicate", }) if err != nil { @@ -279,7 +280,7 @@ func TestProtocolAllowsConcurrentPrincipalConnectionsAndRejectsOversizedFrame(t } wrongServer, wrongClient := net.Pipe() go server.serveConn(wrongServer) - if _, err := NewClient(context.Background(), wrongClient, InitializeParams{ProtocolMajor: 99, ClientKind: "test", ClientID: "wrong"}); err == nil { + if _, err := daemonclient.NewClient(context.Background(), wrongClient, InitializeParams{ProtocolMajor: 99, ClientKind: "test", ClientID: "wrong"}); err == nil { t.Fatal("wrong protocol major initialized") } if err := server.Serve(nil); err == nil { @@ -478,14 +479,14 @@ func TestProtocolBoundsInitializationConnectionsAndInFlightWork(t *testing.T) { // EOF precedes the server goroutine releasing its connection slot. // Retry admission until teardown completes instead of racing that release. - var client *Client + var client *daemonclient.Client deadline := time.Now().Add(time.Second) for { conn, dialErr := (&net.Dialer{}).DialContext(context.Background(), "tcp", listener.Addr().String()) if dialErr != nil { t.Fatal(dialErr) } - client, err = NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "first"}) + client, err = daemonclient.NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "first"}) if err == nil { break } @@ -507,7 +508,7 @@ func TestProtocolBoundsInitializationConnectionsAndInFlightWork(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := NewClient(context.Background(), extra, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "excess"}); err == nil { + if _, err := daemonclient.NewClient(context.Background(), extra, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "excess"}); err == nil { t.Fatal("connection above the configured maximum was initialized") } _ = extra.Close() @@ -576,7 +577,7 @@ func TestInitializedIdleConnectionExpiresAndReleasesItsSlot(t *testing.T) { for { conn, dialErr := (&net.Dialer{}).DialContext(context.Background(), "tcp", listener.Addr().String()) if dialErr == nil { - client, clientErr := NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "replacement"}) + client, clientErr := daemonclient.NewClient(context.Background(), conn, InitializeParams{ProtocolMajor: ProtocolMajor, ClientKind: "test", ClientID: "replacement"}) if clientErr == nil { _ = client.Close() break diff --git a/internal/daemon/session_summaries_test.go b/internal/daemon/session_summaries_test.go index 8225a7823..c00d59ce3 100644 --- a/internal/daemon/session_summaries_test.go +++ b/internal/daemon/session_summaries_test.go @@ -12,6 +12,7 @@ import ( "testing" "unicode/utf8" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -67,7 +68,7 @@ func TestSessionSummariesAcrossTransports(t *testing.T) { } }) } - client, err := DialWebSocketClient(t.Context(), f.endpoint, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "summary-negotiation", ClientKind: "automation", Capabilities: []string{"session_summaries", "unknown", "session_summaries"}}) + client, err := daemonclient.DialWebSocketClient(t.Context(), f.endpoint, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "summary-negotiation", ClientKind: "automation", Capabilities: []string{"session_summaries", "unknown", "session_summaries"}}) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/skill_catalog_completion_test.go b/internal/daemon/skill_catalog_completion_test.go index c32bef6e4..c1e559489 100644 --- a/internal/daemon/skill_catalog_completion_test.go +++ b/internal/daemon/skill_catalog_completion_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/protocol" ) @@ -157,7 +158,7 @@ func TestSkillCatalogCompletionExactByteBoundary(t *testing.T) { func TestSkillCatalogCompletionCapabilityNegotiation(t *testing.T) { fixture := newV2Fixture(t, &fakeRunner{}) for _, requested := range [][]string{nil, {"workspace_completion", "host_skill_completion", "host_global_skill_completion", "skill_catalog_completion", "unknown"}} { - client, err := DialWebSocketClient(t.Context(), fixture.endpoint, InitializeParams{ + client, err := daemonclient.DialWebSocketClient(t.Context(), fixture.endpoint, InitializeParams{ ProtocolMajor: ProtocolMajor, ClientKind: "human", ClientID: "catalog-capability", Capabilities: requested, }) if err != nil { diff --git a/internal/daemon/subscription.go b/internal/daemon/subscription.go index d2953018d..f1e54d1c2 100644 --- a/internal/daemon/subscription.go +++ b/internal/daemon/subscription.go @@ -2,7 +2,6 @@ package daemon import ( "context" - "crypto/rand" "errors" "time" @@ -113,40 +112,3 @@ func (s *Server) pumpSubscription(ctx context.Context, c *serverConn, sub *subsc } } } - -func (c *Client) Subscribe(ctx context.Context, rootID string, cursor int64) (SubscribeResult, error) { - id := rand.Text() - c.mu.Lock() - previous := c.subscriptions[rootID] - c.subscriptions[rootID] = id - c.mu.Unlock() - if previous != "" { - if err := c.Unsubscribe(ctx, previous); err != nil { - return SubscribeResult{}, err - } - } - var result SubscribeResult - err := c.Call(ctx, "events.subscribe", SubscribeParams{RootID: rootID, SubscriptionID: id, Cursor: cursor}, &result) - if err != nil { - c.mu.Lock() - if c.subscriptions[rootID] == id { - delete(c.subscriptions, rootID) - } - c.mu.Unlock() - } - return result, err -} - -func (c *Client) Unsubscribe(ctx context.Context, id string) error { - if err := c.Call(ctx, "events.unsubscribe", UnsubscribeParams{SubscriptionID: id}, nil); err != nil { - return err - } - c.mu.Lock() - for root, active := range c.subscriptions { - if active == id { - delete(c.subscriptions, root) - } - } - c.mu.Unlock() - return nil -} diff --git a/internal/daemon/subscription_lifecycle_test.go b/internal/daemon/subscription_lifecycle_test.go index 7b5b98fe6..67ba788af 100644 --- a/internal/daemon/subscription_lifecycle_test.go +++ b/internal/daemon/subscription_lifecycle_test.go @@ -2,43 +2,10 @@ package daemon import ( "context" - "errors" - "net" "path/filepath" "testing" - - "github.com/context-labs/whip/internal/daemonconn" - "github.com/context-labs/whip/internal/protocol" ) -func TestClientIgnoresFailureFromReplacedSubscription(t *testing.T) { - serverSide, clientSide := net.Pipe() - defer func() { _ = serverSide.Close(); _ = clientSide.Close() }() - stale, _ := marshalFrame(rpcMessage{Method: "subscription.failed", Params: mustJSON(t, protocol.SubscriptionFailure{RootID: "root", SubscriptionID: "old", Error: rpcFailure(-32010, "expired old stream")})}) - current, _ := marshalFrame(rpcMessage{Method: "event", Params: mustJSON(t, daemonconn.EventNotification{Event: ProtocolEvent{RootID: "root", SubscriptionID: "new", Seq: 4, Kind: "turn.started", Payload: []byte(`{}`)}})}) - transport := newUnixMessageTransport(clientSide) - written := make(chan struct{}) - go func() { - defer close(written) - defer serverSide.Close() - _, _ = serverSide.Write(append(stale, current...)) - }() - client := &Client{conn: transport, pending: make(map[string]chan callResponse), subscriptions: map[string]string{"root": "new"}, events: make(chan ProtocolEvent, 2), commandChanged: make(chan struct{}), done: make(chan struct{})} - client.readLoop() - <-written - if _, ok := errors.AsType[*RPCError](client.Err()); ok { - t.Fatalf("stale failure closed current stream: %v", client.Err()) - } - select { - case event := <-client.Events(): - if event.Seq != 4 { - t.Fatalf("event=%+v", event) - } - default: - t.Fatal("current subscription event lost") - } -} - func TestSubscriptionRetirementCannotDeleteReplacement(t *testing.T) { store := openStore(t, filepath.Join(t.TempDir(), "runtime.db")) rootID := createRoot(t, store) diff --git a/internal/daemon/v2_acceptance_test.go b/internal/daemon/v2_acceptance_test.go index b97fde567..1dd93770b 100644 --- a/internal/daemon/v2_acceptance_test.go +++ b/internal/daemon/v2_acceptance_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" @@ -21,7 +22,7 @@ type v2Fixture struct { server *Server store *session.Store rootID string - dial func(string, string) *Client + dial func(string, string) *daemonclient.Client endpoint string } @@ -61,7 +62,7 @@ func newV2Fixture(t *testing.T, runner Runner, origins ...string) v2Fixture { gateway := startTestGateway(t, paths, webgateway.Options{AllowedOrigins: origins}) ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() - initial, err := DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "different-client-build", ClientKind: "human", ClientID: "probe"}) + initial, err := daemonclient.DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "different-client-build", ClientKind: "human", ClientID: "probe"}) if err != nil { t.Fatal(err) } @@ -70,17 +71,17 @@ func newV2Fixture(t *testing.T, runner Runner, origins ...string) v2Fixture { t.Fatal("missing persistent runtime identity") } _ = initial.Close() - return v2Fixture{server: server, gateway: gateway, endpoint: endpoint, store: store, rootID: rootID, dial: func(transport, clientID string) *Client { + return v2Fixture{server: server, gateway: gateway, endpoint: endpoint, store: store, rootID: rootID, dial: func(transport, clientID string) *daemonclient.Client { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() initialize := InitializeParams{ProtocolMajor: ProtocolMajor, BuildID: "different-client-build", ClientKind: "human", ClientID: clientID} - var client *Client + var client *daemonclient.Client var err error if transport == "unix" { - client, err = DialClient(ctx, paths, initialize) + client, err = daemonclient.DialClient(ctx, paths, initialize) } else { - client, err = DialWebSocketClient(ctx, endpoint, initialize) + client, err = daemonclient.DialWebSocketClient(ctx, endpoint, initialize) } if err != nil { t.Fatal(err) diff --git a/internal/daemon/v2_crash_test.go b/internal/daemon/v2_crash_test.go index b1e6c6f70..e40227e4b 100644 --- a/internal/daemon/v2_crash_test.go +++ b/internal/daemon/v2_crash_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" @@ -183,23 +184,23 @@ func serveCrashFixture(t *testing.T, home string, store *session.Store, rootID s gateway := startTestGateway(t, paths, webgateway.Options{}) ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() - initial, err := DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "probe", ClientKind: "test"}) + initial, err := daemonclient.DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "probe", ClientKind: "test"}) if err != nil { t.Fatal(err) } endpoint := "ws" + strings.TrimPrefix(gateway.Endpoint(), "http") + "/api/v3/ws" _ = initial.Close() - return v2Fixture{store: store, rootID: rootID, endpoint: endpoint, dial: func(transport, clientID string) *Client { + return v2Fixture{store: store, rootID: rootID, endpoint: endpoint, dial: func(transport, clientID string) *daemonclient.Client { t.Helper() ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() params := InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: clientID, ClientKind: "test"} - var client *Client + var client *daemonclient.Client var err error if transport == "unix" { - client, err = DialClient(ctx, paths, params) + client, err = daemonclient.DialClient(ctx, paths, params) } else { - client, err = DialWebSocketClient(ctx, endpoint, params) + client, err = daemonclient.DialWebSocketClient(ctx, endpoint, params) } if err != nil { t.Fatal(err) diff --git a/internal/daemon/v2_latency_test.go b/internal/daemon/v2_latency_test.go index c24e21400..a6af13e19 100644 --- a/internal/daemon/v2_latency_test.go +++ b/internal/daemon/v2_latency_test.go @@ -9,6 +9,8 @@ import ( "sync" "testing" "time" + + daemonclient "github.com/context-labs/whip/internal/client" ) // Report latency without making machine-dependent performance a correctness gate. @@ -18,7 +20,7 @@ func TestV2ConcurrentAdmissionAndEventLatency(t *testing.T) { fixture := newV2Fixture(t, &fakeRunner{}) const agents, rounds = 4, 12 roots := make([]string, agents) - clients := make([]*Client, agents) + clients := make([]*daemonclient.Client, agents) ctx, cancel := context.WithTimeout(t.Context(), 20*time.Second) defer cancel() for i := range agents { diff --git a/internal/daemon/v2_sdk_test.go b/internal/daemon/v2_sdk_test.go index 9200ae2a4..80c63edf7 100644 --- a/internal/daemon/v2_sdk_test.go +++ b/internal/daemon/v2_sdk_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" @@ -208,7 +209,7 @@ func TestV2SDKBridge(t *testing.T) { gateway := startTestGateway(t, paths, network) ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() - probe, err := DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "sdk-probe", ClientKind: "automation"}) + probe, err := daemonclient.DialClient(ctx, paths, InitializeParams{ProtocolMajor: ProtocolMajor, ClientID: "sdk-probe", ClientKind: "automation"}) if err != nil { t.Fatal(err) } diff --git a/internal/daemon/view.go b/internal/daemon/view.go index ebc25f73d..3f35d8630 100644 --- a/internal/daemon/view.go +++ b/internal/daemon/view.go @@ -54,19 +54,6 @@ func (s *Server) historyPage(ctx context.Context, params HistoryPageParams) (ses }) } -func (c *Client) HistoryPage(ctx context.Context, params HistoryPageParams) (session.BoundedTranscriptPage, error) { - var page session.BoundedTranscriptPage - err := c.Call(ctx, "history.page", params, &page) - return page, err -} - -// TracePage reads a root's spans after a cursor; see protocol.TracePageParams. -func (c *Client) TracePage(ctx context.Context, params protocol.TracePageParams) (session.SpanPage, error) { - var page session.SpanPage - err := c.Call(ctx, "trace.page", params, &page) - return page, err -} - // traceExport renders the OTLP/JSON export and parks it in the root's content // store as a reference, so any client fetches it through the existing bounded // content reads regardless of size. @@ -85,10 +72,3 @@ func (s *Server) traceExport(ctx context.Context, params protocol.TraceExportPar Content: ContentHandle{ReferenceID: value.ReferenceID, Digest: value.Digest, Size: value.Size, MediaType: value.MediaType, Source: value.Source}, }, nil } - -// TraceExport renders a session as OTLP/JSON; see protocol.TraceExportParams. -func (c *Client) TraceExport(ctx context.Context, params protocol.TraceExportParams) (protocol.TraceExportResult, error) { - var result protocol.TraceExportResult - err := c.Call(ctx, "trace.export", params, &result) - return result, err -} diff --git a/internal/tui/client.go b/internal/tui/client.go index d77ce6bdd..601837171 100644 --- a/internal/tui/client.go +++ b/internal/tui/client.go @@ -15,37 +15,37 @@ import ( "charm.land/bubbles/v2/spinner" "charm.land/bubbles/v2/textinput" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/daemonconn" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" bubbletea "charm.land/bubbletea/v2" "github.com/charmbracelet/colorprofile" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tui/theme" "github.com/context-labs/whip/internal/update" ) -type ClientState = daemon.RootClientState +type ClientState = daemonclient.RootClientState const ( - ClientDisconnected = daemon.RootDisconnected - ClientReconnecting = daemon.RootReconnecting - ClientSnapshotting = daemon.RootSnapshotting - ClientLive = daemon.RootLive + ClientDisconnected = daemonclient.RootDisconnected + ClientReconnecting = daemonclient.RootReconnecting + ClientSnapshotting = daemonclient.RootSnapshotting + ClientLive = daemonclient.RootLive ) type ( - Action = daemon.RootAction - ClientUpdate = daemon.RootUpdate - daemonConnection = daemon.RootConnection - ClientOptions = daemon.RootClientOptions - Client = daemon.RootClient + Action = daemonclient.RootAction + ClientUpdate = daemonclient.RootUpdate + daemonConnection = daemonclient.RootConnection + ClientOptions = daemonclient.RootClientOptions + Client = daemonclient.RootClient ) -func NewClient(options ClientOptions) (*Client, error) { return daemon.NewRootClient(options) } +func NewClient(options ClientOptions) (*Client, error) { return daemonclient.NewRootClient(options) } // clientPresentation is the daemon-fed state needed to render a terminal. It // deliberately has no provider client, tool registry, scheduler, store, or @@ -87,8 +87,8 @@ func Run(cfg *config.Config, modelName, provName, resumeID string, cautious, yol clientID := "tui-" + rand.Text() resumeChecked := false connector := func(ctx context.Context, cursors map[string]int64) (daemonConnection, error) { - connection, err := daemon.EnsureClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, BuildID: Version, ClientKind: "tui", + connection, err := daemonclient.EnsureClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, BuildID: Version, ClientKind: "tui", ClientID: clientID, Capabilities: []string{"commands", "events", "snapshots", "permissions"}, Cursors: cursors, }, func() error { return daemonconn.LaunchSelfDaemon(paths) }) @@ -115,9 +115,9 @@ func Run(cfg *config.Config, modelName, provName, resumeID string, cautious, yol resumeChecked = true return connection, nil } - var create *daemon.CreateSession + var create *session.CreateSession if resumeID == "" { - create = &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: cwd(), Model: modelName, Provider: provName, ExecutionEngine: engine, Definition: definition} + create = &session.CreateSession{Kind: session.SessionKindAgent, CWD: cwd(), Model: modelName, Provider: provName, ExecutionEngine: engine, Definition: definition} } client, err := NewClient(ClientOptions{ ClientID: clientID, @@ -230,18 +230,18 @@ type clientSnapshotMsg struct { } type clientCommandMsg struct { action Action - result daemon.CommandResult + result protocol.CommandResult err error } type clientPermissionMsg struct { action Action permissionID string - result daemon.PermissionDecisionResult + result protocol.PermissionDecisionResult err error } type clientTerminalMsg struct { action Action - result daemon.CommandResult + result protocol.CommandResult err error } @@ -412,7 +412,7 @@ func pendingUserText(item session.InboxItem) string { case "submit", "steer": return string(item.Payload.Inline) case "submit.parts", "steer.parts": - var payload daemon.SubmitPayload + var payload protocol.SubmitPayload if json.Unmarshal(item.Payload.Inline, &payload) != nil { return "" } @@ -493,11 +493,11 @@ func (m *model) displayContextLimit() int { return m.clientView.contextLimit } -func (m *model) recordClientStream(event daemon.ProtocolEvent) { +func (m *model) recordClientStream(event protocol.ProtocolEvent) { if !strings.HasPrefix(event.Kind, "stream.") || event.Kind == "stream.accounting" { return } - var payload daemon.StreamEvent + var payload protocol.StreamEvent if json.Unmarshal(event.Payload, &payload) != nil { return } @@ -522,8 +522,8 @@ func (m *model) applyClientStream(kind string, payload []byte) (bool, bubbletea. return false, nil } var omitted struct { - Truncated bool `json:"truncated"` - Content *daemon.ContentHandle `json:"content"` + Truncated bool `json:"truncated"` + Content *protocol.ContentHandle `json:"content"` } // Host outcomes live in the REPL panel, which reads the retained small fields. if json.Unmarshal(payload, &omitted) == nil && omitted.Truncated && !strings.HasPrefix(kind, "stream.cell.host") { @@ -534,7 +534,7 @@ func (m *model) applyClientStream(kind string, payload []byte) (bool, bubbletea. m.append(dimStyle.Render(detail)) return true, nil } - var event daemon.StreamEvent + var event protocol.StreamEvent if err := json.Unmarshal(payload, &event); err != nil { m.append(errStyle.Render("daemon stream: " + err.Error())) return true, nil @@ -616,7 +616,7 @@ func (m *model) applyClientStream(kind string, payload []byte) (bool, bubbletea. } return true, nil case "stream.plan": - var plan daemon.PlanEvent + var plan protocol.PlanEvent if err := json.Unmarshal([]byte(event.Result), &plan); err != nil { m.append(errStyle.Render("daemon plan: " + err.Error())) return true, nil @@ -750,7 +750,7 @@ func mergePresentation(snapshot, current []session.SnapshotEvent, cursor int64) return merged } -func (m *model) openAgent(result daemon.AgentTranscriptResult) { +func (m *model) openAgent(result protocol.AgentTranscriptResult) { m.agentOpen = result.Agent.ID m.agentMessages[result.Agent.ID] = pageMessages(result.Page) m.setHistoryPage(result.Agent.ID, result.Page) @@ -800,7 +800,7 @@ func (m *model) cancelVisibleTurn() (bubbletea.Model, bubbletea.Cmd) { func (m *model) applyClientLifecycle(kind string, payload []byte) (bool, bubbletea.Cmd) { if strings.HasPrefix(kind, "session.") && strings.HasSuffix(kind, ".updated") { - var event daemon.SessionUpdateEvent + var event protocol.SessionUpdateEvent if err := json.Unmarshal(payload, &event); err != nil { return false, nil } @@ -1371,7 +1371,7 @@ func (m *model) thinKey(msg bubbletea.KeyPressMsg) (bubbletea.Model, bubbletea.C if m.agentOpen != "" { return m.submitClientAction("agent.submit", map[string]string{"id": m.agentOpen, "text": sent, "delivery": "steer"}, text) } - return m.submitClientAction("steer", daemon.SubmitPayload{Text: sent}, text) + return m.submitClientAction("steer", protocol.SubmitPayload{Text: sent}, text) default: return m, nil } @@ -2073,4 +2073,4 @@ func (m *model) thinCommand(text string) (bubbletea.Model, bubbletea.Cmd) { return m.submitClientCLI(operation, args) } -var _ daemonConnection = (*daemon.Client)(nil) +var _ daemonConnection = (*daemonclient.Client)(nil) diff --git a/internal/tui/client_completion.go b/internal/tui/client_completion.go index dc26a9af8..a0d5bbd4d 100644 --- a/internal/tui/client_completion.go +++ b/internal/tui/client_completion.go @@ -5,8 +5,9 @@ import ( "strings" "time" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" - "github.com/context-labs/whip/internal/daemon" ) type clientCompletion struct { @@ -21,7 +22,7 @@ type clientCompletion struct { type clientCompletionMsg struct { request *clientCompletion - result daemon.CompletionResult + result protocol.CompletionResult err error } @@ -80,7 +81,7 @@ func (m *model) completionCandidates(value string, explicit bool) (string, []can case <-timer.C: } } - result, err := client.CompleteWorkspace(ctx, daemon.CompletionParams{RootID: request.rootID, AgentID: request.agentID, Kind: kind, Prefix: prefix, Limit: 64}) + result, err := client.CompleteWorkspace(ctx, protocol.CompletionParams{RootID: request.rootID, AgentID: request.agentID, Kind: kind, Prefix: prefix, Limit: 64}) if ctx.Err() == context.Canceled && err != nil { return } @@ -135,7 +136,7 @@ func (m *model) requestHostSkills() tea.Cmd { return func() tea.Msg { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - result, err := client.CompleteWorkspace(ctx, daemon.CompletionParams{RootID: rootID, Kind: "skill", Limit: 64}) + result, err := client.CompleteWorkspace(ctx, protocol.CompletionParams{RootID: rootID, Kind: "skill", Limit: 64}) if err != nil { return nil } diff --git a/internal/tui/client_completion_test.go b/internal/tui/client_completion_test.go index 64156b9cd..ea85d0c79 100644 --- a/internal/tui/client_completion_test.go +++ b/internal/tui/client_completion_test.go @@ -3,7 +3,6 @@ package tui import ( "testing" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" ) @@ -13,7 +12,7 @@ func TestHostCompletionRejectsStaleInputAndRoot(t *testing.T) { old := &clientCompletion{value: "@ma", rootID: m.sessionID} current := &clientCompletion{value: "@main", rootID: m.sessionID} m.hostCompletion = current - result := daemon.CompletionResult{Candidates: []protocol.CompletionCandidate{{Text: "@main.go"}}} + result := protocol.CompletionResult{Candidates: []protocol.CompletionCandidate{{Text: "@main.go"}}} m.applyHostCompletion(clientCompletionMsg{request: old, result: result}) if m.menu != nil { t.Fatal("stale request installed menu") diff --git a/internal/tui/client_export.go b/internal/tui/client_export.go index 4a2f954f3..fac017c76 100644 --- a/internal/tui/client_export.go +++ b/internal/tui/client_export.go @@ -11,7 +11,6 @@ import ( "os" "path/filepath" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -22,7 +21,7 @@ type clientExportMsg struct { err error } type transcriptExporter interface { - HistoryPage(context.Context, daemon.HistoryPageParams) (session.BoundedTranscriptPage, error) + HistoryPage(context.Context, protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) ReadContent(context.Context, protocol.ContentReadParams) (protocol.ContentReadResult, error) } @@ -37,7 +36,7 @@ func exportHostTranscript(ctx context.Context, host transcriptExporter, path, ro if _, err = io.WriteString(file, "# Session transcript\n\n"); err != nil { return err } - params := daemon.HistoryPageParams{RootID: rootID, AgentID: agentID, ThroughSeq: -1, Limit: 64, MaxBytes: 256 << 10} + params := protocol.HistoryPageParams{RootID: rootID, AgentID: agentID, ThroughSeq: -1, Limit: 64, MaxBytes: 256 << 10} for { page, err := host.HistoryPage(ctx, params) if err != nil { @@ -85,7 +84,7 @@ func exportHostTranscript(ctx context.Context, host transcriptExporter, path, ro } func readTranscriptBody(ctx context.Context, host transcriptExporter, rootID, agentID string, body session.RuntimeValue) (*llm.Message, error) { - if body.Size < 0 || body.Size > daemon.MaxUploadSize { + if body.Size < 0 || body.Size > session.MaxInputPayloadBytes { return nil, errors.New("transcript body exceeds transfer limit") } data := make([]byte, 0, int(body.Size)) diff --git a/internal/tui/client_export_test.go b/internal/tui/client_export_test.go index 9ec7a5727..cac227180 100644 --- a/internal/tui/client_export_test.go +++ b/internal/tui/client_export_test.go @@ -11,7 +11,6 @@ import ( "strings" "testing" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" @@ -24,7 +23,7 @@ type exportTestHost struct { fail bool } -func (h *exportTestHost) HistoryPage(_ context.Context, p daemon.HistoryPageParams) (session.BoundedTranscriptPage, error) { +func (h *exportTestHost) HistoryPage(_ context.Context, p protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) { h.pages++ if p.RootID != "root" || p.AgentID != "child" || p.Limit > 64 || p.MaxBytes > 256<<10 { return session.BoundedTranscriptPage{}, errors.New("unbounded or wrong scope") diff --git a/internal/tui/client_history.go b/internal/tui/client_history.go index 5e8641a97..adf681952 100644 --- a/internal/tui/client_history.go +++ b/internal/tui/client_history.go @@ -6,8 +6,9 @@ import ( "slices" "time" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -120,7 +121,7 @@ func (m *model) requestOlderHistory() tea.Cmd { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() revision := request.revision - page, err := client.HistoryPage(ctx, daemon.HistoryPageParams{ + page, err := client.HistoryPage(ctx, protocol.HistoryPageParams{ RootID: request.rootID, AgentID: request.agentID, BeforeSeq: request.before, ThroughSeq: request.through, Revision: &revision, Limit: 64, MaxBytes: 256 << 10, Recent: true, }) diff --git a/internal/tui/client_history_test.go b/internal/tui/client_history_test.go index 631bde402..7b42595bd 100644 --- a/internal/tui/client_history_test.go +++ b/internal/tui/client_history_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -88,10 +88,10 @@ func TestLargeHistoryMessageExplicitlyIdentifiesContentReference(t *testing.T) { type historyConnection struct { *fakeDaemonConnection - requests chan daemon.HistoryPageParams + requests chan protocol.HistoryPageParams } -func (c *historyConnection) HistoryPage(ctx context.Context, p daemon.HistoryPageParams) (session.BoundedTranscriptPage, error) { +func (c *historyConnection) HistoryPage(ctx context.Context, p protocol.HistoryPageParams) (session.BoundedTranscriptPage, error) { c.requests <- p return session.BoundedTranscriptPage{HistoryRevision: *p.Revision, NextSeq: 1, Messages: []session.TranscriptPageEntry{}}, nil } @@ -101,7 +101,7 @@ func TestScrollHistoryRequestsOneBoundedPage(t *testing.T) { RootID: "root", HistoryRevision: 7, FirstMessageSeq: 100, MessageSeqs: []int{100}, Omitted: map[string]bool{"messages": true}, Meta: session.Meta{ID: "root"}, Messages: []llm.Message{{Role: "user", Content: "recent"}}, } - connection := &historyConnection{fakeDaemonConnection: newFakeDaemonConnection(snapshot), requests: make(chan daemon.HistoryPageParams, 1)} + connection := &historyConnection{fakeDaemonConnection: newFakeDaemonConnection(snapshot), requests: make(chan protocol.HistoryPageParams, 1)} client, err := NewClient(ClientOptions{ ClientID: "tui", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, Connector: func(context.Context, map[string]int64) (daemonConnection, error) { return connection, nil }, diff --git a/internal/tui/client_integration_test.go b/internal/tui/client_integration_test.go index 5098dbc64..4ca4d0926 100644 --- a/internal/tui/client_integration_test.go +++ b/internal/tui/client_integration_test.go @@ -15,6 +15,7 @@ import ( "time" "github.com/context-labs/whip/internal/capability" + daemonclient "github.com/context-labs/whip/internal/client" "github.com/context-labs/whip/internal/config" "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/daemonconn" @@ -86,14 +87,14 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { }) ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second) defer cancel() - initialize := daemon.InitializeParams{ProtocolMajor: daemon.ProtocolMajor, ClientID: "tui-startup", ClientKind: "tui"} + initialize := protocol.InitializeParams{ProtocolMajor: protocol.Major, ClientID: "tui-startup", ClientKind: "tui"} var endpoint string if transport == "websocket" { gateway, err := webgateway.Start(t.Context(), webgateway.Options{ Address: "127.0.0.1:0", SocketPath: paths.Socket, Open: func(ctx context.Context) (webgateway.Client, error) { - return daemon.DialClient(ctx, paths, daemon.InitializeParams{ - ProtocolMajor: daemon.ProtocolMajor, ClientID: "tui-gateway-" + rand.Text(), ClientKind: "gateway", + return daemonclient.DialClient(ctx, paths, protocol.InitializeParams{ + ProtocolMajor: protocol.Major, ClientID: "tui-gateway-" + rand.Text(), ClientKind: "gateway", Capabilities: []string{protocol.NetworkClientCapability}, }) }, @@ -110,14 +111,14 @@ func TestInteractiveSessionOverTrustedProtocol(t *testing.T) { } client, err := NewClient(ClientOptions{ ClientID: initialize.ClientID, - Create: &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: home}, + Create: &session.CreateSession{Kind: session.SessionKindAgent, CWD: home}, Connector: func(ctx context.Context, cursors map[string]int64) (daemonConnection, error) { params := initialize params.Cursors = cursors if transport == "websocket" { - return daemon.DialWebSocketClient(ctx, endpoint, params) + return daemonclient.DialWebSocketClient(ctx, endpoint, params) } - return daemon.DialClient(ctx, paths, params) + return daemonclient.DialClient(ctx, paths, params) }, }) if err != nil { diff --git a/internal/tui/client_queue_test.go b/internal/tui/client_queue_test.go index d5ebe093e..7e26bac97 100644 --- a/internal/tui/client_queue_test.go +++ b/internal/tui/client_queue_test.go @@ -7,10 +7,10 @@ import ( "testing" "time" - tea "charm.land/bubbletea/v2" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -101,7 +101,7 @@ func TestTurnFailureIsVisibleOnce(t *testing.T) { if err != nil { t.Fatal(err) } - updated, _ := m.Update(clientCommandMsg{action: action, result: daemon.CommandResult{Status: "failed", Error: "provider unavailable"}}) + updated, _ := m.Update(clientCommandMsg{action: action, result: protocol.CommandResult{Status: "failed", Error: "provider unavailable"}}) m = updated.(*model) if m.busy || strings.Count(m.transcriptText(), "provider unavailable") != 1 { t.Fatalf("after command failure busy=%v transcript=%q", m.busy, m.transcriptText()) @@ -172,8 +172,8 @@ func TestRecursiveAgentTreeAndScopedStreams(t *testing.T) { t.Fatalf("root then depth-first rows=%+v", rows) } m.agentOpen = "a" - rootPayload, _ := json.Marshal(daemon.StreamEvent{AgentID: "root-agent", Text: "root-only"}) - childPayload, _ := json.Marshal(daemon.StreamEvent{AgentID: "a", Text: "child-only"}) + rootPayload, _ := json.Marshal(protocol.StreamEvent{AgentID: "root-agent", Text: "root-only"}) + childPayload, _ := json.Marshal(protocol.StreamEvent{AgentID: "a", Text: "child-only"}) _, _ = m.applyClientStream("stream.text", rootPayload) if m.current != "" { t.Fatalf("root stream contaminated child view: %q", m.current) @@ -218,8 +218,8 @@ func TestScopedStreamsRemainAvailableAcrossPaneNavigation(t *testing.T) { agentPresentations: map[string][]session.SnapshotEvent{}, }, } - payload, _ := json.Marshal(daemon.StreamEvent{AgentID: "root-agent", Text: "root progress\n"}) - event := daemon.ProtocolEvent{Seq: 4, Kind: "stream.text", Payload: payload} + payload, _ := json.Marshal(protocol.StreamEvent{AgentID: "root-agent", Text: "root progress\n"}) + event := protocol.ProtocolEvent{Seq: 4, Kind: "stream.text", Payload: payload} m.recordClientStream(event) if handled, _ := m.applyClientStream(event.Kind, event.Payload); !handled || strings.Contains(m.transcriptText(), "root progress") { t.Fatalf("root stream contaminated selected child: %q", m.transcriptText()) @@ -313,7 +313,7 @@ func TestSessionMetadataEventsUpdateHeaderRouteAndContext(t *testing.T) { Models: []config.ModelInfoLite{{ID: "api-next", ContextLength: 256}}, }}, } - payload, _ := json.Marshal(daemon.SessionUpdateEvent{ + payload, _ := json.Marshal(protocol.SessionUpdateEvent{ Title: "renamed", Model: "next-model", Provider: "next-provider", Effort: "off", EffortChanged: true, WorkingDir: "/tmp/project", }) if handled, _ := m.applyClientLifecycle("session.model.updated", payload); !handled { @@ -349,7 +349,7 @@ func TestSnapshotShowsSavedEffortVerbatim(t *testing.T) { } func TestSnapshotPreservesQueuesFocusModalAndToolExpansion(t *testing.T) { - encode := func(event daemon.StreamEvent) []byte { + encode := func(event protocol.StreamEvent) []byte { payload, err := json.Marshal(event) if err != nil { t.Fatal(err) @@ -357,8 +357,8 @@ func TestSnapshotPreservesQueuesFocusModalAndToolExpansion(t *testing.T) { return payload } presentation := []session.SnapshotEvent{ - {Seq: 1, Kind: "stream.tool.started", Payload: encode(daemon.StreamEvent{AgentID: "root-agent", ID: "tool", Name: "read", Args: `{"path":"a.go"}`})}, - {Seq: 2, Kind: "stream.tool.completed", Payload: encode(daemon.StreamEvent{AgentID: "root-agent", ID: "tool", Name: "read", Result: "result"})}, + {Seq: 1, Kind: "stream.tool.started", Payload: encode(protocol.StreamEvent{AgentID: "root-agent", ID: "tool", Name: "read", Args: `{"path":"a.go"}`})}, + {Seq: 2, Kind: "stream.tool.completed", Payload: encode(protocol.StreamEvent{AgentID: "root-agent", ID: "tool", Name: "read", Result: "result"})}, } snapshot := session.RootSnapshot{ RootID: "root", Cursor: 2, Meta: session.Meta{ID: "root", Model: "kimi-k3-fast", Provider: "inference"}, @@ -397,7 +397,7 @@ func TestSnapshotPreservesQueuesFocusModalAndToolExpansion(t *testing.T) { } func TestSnapshotRebuildsInProgressUserInputAndChildPresentation(t *testing.T) { - stream, _ := json.Marshal(daemon.StreamEvent{AgentID: "child", Text: "working\n"}) + stream, _ := json.Marshal(protocol.StreamEvent{AgentID: "child", Text: "working\n"}) m := &model{ input: newInput(), agentOpen: "child", agentMessages: map[string][]llm.Message{}, @@ -412,7 +412,7 @@ func TestSnapshotRebuildsInProgressUserInputAndChildPresentation(t *testing.T) { t.Fatalf("running transcript was not rebuilt exactly once: %q", transcript) } - m.openAgent(daemon.AgentTranscriptResult{ + m.openAgent(protocol.AgentTranscriptResult{ Cursor: 10, Agent: session.RuntimeAgent{ID: "child", ParentID: "root-agent", LifecyclePhase: "running"}, Inbox: []session.InboxItem{{AgentID: "child", Seq: 5, Kind: "submit", Status: "queued", Payload: session.RuntimeValue{Inline: []byte("follow up")}}}, diff --git a/internal/tui/client_test.go b/internal/tui/client_test.go index b4d8f089f..a7925b9f1 100644 --- a/internal/tui/client_test.go +++ b/internal/tui/client_test.go @@ -9,39 +9,38 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/session" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" - "github.com/context-labs/whip/internal/protocol" - "github.com/context-labs/whip/internal/session" ) type fakeDaemonConnection struct { mu sync.Mutex - commands []daemon.CommandParams - replay daemon.ReplayResult + commands []protocol.CommandParams + replay protocol.ReplayResult snapshot session.RootSnapshot - events chan daemon.ProtocolEvent + events chan protocol.ProtocolEvent done chan struct{} err error closeOnce sync.Once - commandFunc func(daemon.CommandParams) (daemon.CommandResult, error) - decisions []daemon.PermissionDecision - subscriptions []daemon.SubscribeParams + commandFunc func(protocol.CommandParams) (protocol.CommandResult, error) + decisions []protocol.PermissionDecision + subscriptions []protocol.SubscribeParams } func newFakeDaemonConnection(snapshot session.RootSnapshot) *fakeDaemonConnection { return &fakeDaemonConnection{ - snapshot: snapshot, events: make(chan daemon.ProtocolEvent, 16), done: make(chan struct{}), + snapshot: snapshot, events: make(chan protocol.ProtocolEvent, 16), done: make(chan struct{}), } } -func (f *fakeDaemonConnection) Command(_ context.Context, params daemon.CommandParams) (daemon.CommandResult, error) { +func (f *fakeDaemonConnection) Command(_ context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { if err := protocol.ValidateRuntime(params.Operation, params.Payload); err != nil { - return daemon.CommandResult{}, err + return protocol.CommandResult{}, err } f.mu.Lock() defer f.mu.Unlock() @@ -49,10 +48,10 @@ func (f *fakeDaemonConnection) Command(_ context.Context, params daemon.CommandP if f.commandFunc != nil { return f.commandFunc(params) } - return daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded"}, nil + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded"}, nil } -func (f *fakeDaemonConnection) Replay(context.Context, daemon.ReplayParams) (daemon.ReplayResult, error) { +func (f *fakeDaemonConnection) Replay(context.Context, protocol.ReplayParams) (protocol.ReplayResult, error) { return f.replay, nil } @@ -60,16 +59,16 @@ func (f *fakeDaemonConnection) Snapshot(context.Context, string) (session.RootSn return f.snapshot, nil } -func (f *fakeDaemonConnection) DecidePermission(_ context.Context, decision daemon.PermissionDecision) (daemon.PermissionDecisionResult, error) { +func (f *fakeDaemonConnection) DecidePermission(_ context.Context, decision protocol.PermissionDecision) (protocol.PermissionDecisionResult, error) { f.mu.Lock() defer f.mu.Unlock() f.decisions = append(f.decisions, decision) - return daemon.PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil + return protocol.PermissionDecisionResult{OperationID: "operation", LeaseID: "lease"}, nil } -func (f *fakeDaemonConnection) Events() <-chan daemon.ProtocolEvent { return f.events } -func (f *fakeDaemonConnection) Done() <-chan struct{} { return f.done } -func (f *fakeDaemonConnection) Err() error { return f.err } +func (f *fakeDaemonConnection) Events() <-chan protocol.ProtocolEvent { return f.events } +func (f *fakeDaemonConnection) Done() <-chan struct{} { return f.done } +func (f *fakeDaemonConnection) Err() error { return f.err } func (f *fakeDaemonConnection) Close() error { f.closeOnce.Do(func() { close(f.done) }) return nil @@ -136,7 +135,7 @@ func TestInteractiveSetupAppliesYoloModeOnlyToInitialSession(t *testing.T) { t.Fatal(err) } connection.mu.Lock() - commands := append([]daemon.CommandParams(nil), connection.commands...) + commands := append([]protocol.CommandParams(nil), connection.commands...) connection.mu.Unlock() if len(commands) != 1 || commands[0].Operation != "permission.mode" || !strings.Contains(string(commands[0].Payload), `"external_permissions":false`) { t.Fatalf("yolo setup commands=%+v", commands) @@ -197,7 +196,7 @@ func TestClientPermissionLabelFollowsSessionSnapshotsAndEvents(t *testing.T) { t.Fatalf("other session retained full access label: %q", m.ocModeLabel()) } for _, mode := range []string{"automatic", "prompt"} { - payload, err := json.Marshal(daemon.SessionUpdateEvent{PermissionMode: &mode}) + payload, err := json.Marshal(protocol.SessionUpdateEvent{PermissionMode: &mode}) if err != nil { t.Fatal(err) } @@ -212,11 +211,11 @@ func TestClientPermissionLabelFollowsSessionSnapshotsAndEvents(t *testing.T) { func TestInteractiveSetupStopsWhenCautiousModeFails(t *testing.T) { connection := newFakeDaemonConnection(session.RootSnapshot{RootID: "root"}) - connection.commandFunc = func(params daemon.CommandParams) (daemon.CommandResult, error) { + connection.commandFunc = func(params protocol.CommandParams) (protocol.CommandResult, error) { if params.Operation == "permission.mode" { - return daemon.CommandResult{CommandID: params.CommandID, Status: "failed", Error: "mode change rejected"}, nil + return protocol.CommandResult{CommandID: params.CommandID, Status: "failed", Error: "mode change rejected"}, nil } - return daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded"}, nil + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded"}, nil } client, err := NewClient(ClientOptions{ ClientID: "tui", RootID: "root", RetryMin: time.Millisecond, RetryMax: time.Millisecond, @@ -239,7 +238,7 @@ func TestInteractiveSetupStopsWhenCautiousModeFails(t *testing.T) { func TestCatalogRefreshEchoOnlyWhenExplicit(t *testing.T) { t.Setenv("WHIPCODE_HOME", t.TempDir()) - catalogsResult := daemon.CommandResult{Status: "succeeded", Output: `{"catalogs":{"anthropic":{}}}`} + catalogsResult := protocol.CommandResult{Status: "succeeded", Output: `{"catalogs":{"anthropic":{}}}`} // Background refresh (startup, auth): no "refreshed" echo, flag untouched. m, _ := liveQueueModel(t) @@ -324,12 +323,12 @@ func TestClientSnapshotEventsAndStableActions(t *testing.T) { t.Fatalf("daemon command = %+v", got) } - connection.events <- daemon.ProtocolEvent{RootID: "root", Seq: 3, Kind: "text", Payload: []byte("answer")} + connection.events <- protocol.ProtocolEvent{RootID: "root", Seq: 3, Kind: "text", Payload: []byte("answer")} update := nextClientUpdate(t, client) if update.Event == nil || update.Event.Seq != 3 || client.Cursor() != 3 { t.Fatalf("event update = %+v cursor=%d", update, client.Cursor()) } - connection.events <- daemon.ProtocolEvent{RootID: "root", Seq: 3, Kind: "duplicate"} + connection.events <- protocol.ProtocolEvent{RootID: "root", Seq: 3, Kind: "duplicate"} select { case duplicate := <-client.Updates(): t.Fatalf("duplicate event was published: %+v", duplicate) @@ -340,7 +339,7 @@ func TestClientSnapshotEventsAndStableActions(t *testing.T) { func TestClientReconnectReplayAndSnapshotFallback(t *testing.T) { first := newFakeDaemonConnection(session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root"}}) second := newFakeDaemonConnection(session.RootSnapshot{RootID: "root", Cursor: 9, Meta: session.Meta{ID: "root"}}) - second.replay = daemon.ReplayResult{Expired: true, Latest: 9} + second.replay = protocol.ReplayResult{Expired: true, Latest: 9} var mu sync.Mutex var calls int var reconnectCursor int64 @@ -366,7 +365,7 @@ func TestClientReconnectReplayAndSnapshotFallback(t *testing.T) { client.Start() defer client.Close() waitClientState(t, client, ClientLive) - first.events <- daemon.ProtocolEvent{RootID: "root", Seq: 1, Kind: "turn.started"} + first.events <- protocol.ProtocolEvent{RootID: "root", Seq: 1, Kind: "turn.started"} for update := nextClientUpdate(t, client); update.Event == nil; update = nextClientUpdate(t, client) { } first.err = errors.New("lost socket") @@ -389,13 +388,13 @@ func TestClientReconnectReplayAndSnapshotFallback(t *testing.T) { func TestClientReattachesInFlightActionWithSameIdentityAfterDisconnect(t *testing.T) { first := newFakeDaemonConnection(session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root"}}) first.err = errors.New("socket lost after admission") - first.commandFunc = func(daemon.CommandParams) (daemon.CommandResult, error) { + first.commandFunc = func(protocol.CommandParams) (protocol.CommandResult, error) { _ = first.Close() - return daemon.CommandResult{}, first.err + return protocol.CommandResult{}, first.err } second := newFakeDaemonConnection(session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root"}}) - second.commandFunc = func(params daemon.CommandParams) (daemon.CommandResult, error) { - return daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "persisted outcome"}, nil + second.commandFunc = func(params protocol.CommandParams) (protocol.CommandResult, error) { + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "persisted outcome"}, nil } var connects int client, err := NewClient(ClientOptions{ @@ -435,12 +434,12 @@ func TestClientReattachesInFlightActionWithSameIdentityAfterDisconnect(t *testin func TestClientCreatesThenSubscribesOnSameConnection(t *testing.T) { creation := newFakeDaemonConnection(session.RootSnapshot{RootID: "new-root", Meta: session.Meta{ID: "new-root"}}) - creation.commandFunc = func(params daemon.CommandParams) (daemon.CommandResult, error) { - return daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "new-root"}, nil + creation.commandFunc = func(params protocol.CommandParams) (protocol.CommandResult, error) { + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "new-root"}, nil } var calls int client, err := NewClient(ClientOptions{ - ClientID: "tui", Create: &daemon.CreateSession{CWD: "/work", Model: "m", Provider: "p"}, + ClientID: "tui", Create: &session.CreateSession{CWD: "/work", Model: "m", Provider: "p"}, RetryMin: time.Millisecond, RetryMax: time.Millisecond, Connector: func(_ context.Context, cursors map[string]int64) (daemonConnection, error) { calls++ @@ -654,20 +653,20 @@ func TestDaemonBackedModelRendersWithoutAnAgent(t *testing.T) { } func TestClientStreamEventsRenderLiveAndSnapshotRestoresThem(t *testing.T) { - stream := func(kind string, event daemon.StreamEvent) daemon.ProtocolEvent { + stream := func(kind string, event protocol.StreamEvent) protocol.ProtocolEvent { payload, err := json.Marshal(event) if err != nil { t.Fatal(err) } - return daemon.ProtocolEvent{RootID: "root", Kind: kind, Payload: payload} + return protocol.ProtocolEvent{RootID: "root", Kind: kind, Payload: payload} } m := &model{input: newInput(), follow: true, showThinking: true} - for _, event := range []daemon.ProtocolEvent{ - stream("stream.reasoning", daemon.StreamEvent{Text: "considering"}), - stream("stream.text", daemon.StreamEvent{Text: "hello"}), - stream("stream.tool.call", daemon.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a"}`}), - stream("stream.tool.started", daemon.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a"}`}), - stream("stream.tool.completed", daemon.StreamEvent{ID: "tool-1", Name: "read", Result: "done"}), + for _, event := range []protocol.ProtocolEvent{ + stream("stream.reasoning", protocol.StreamEvent{Text: "considering"}), + stream("stream.text", protocol.StreamEvent{Text: "hello"}), + stream("stream.tool.call", protocol.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a"}`}), + stream("stream.tool.started", protocol.StreamEvent{ID: "tool-1", Name: "read", Args: `{"path":"a"}`}), + stream("stream.tool.completed", protocol.StreamEvent{ID: "tool-1", Name: "read", Result: "done"}), } { if handled, _ := m.applyClientStream(event.Kind, event.Payload); !handled { t.Fatalf("event %q was not handled", event.Kind) @@ -678,9 +677,9 @@ func TestClientStreamEventsRenderLiveAndSnapshotRestoresThem(t *testing.T) { } presentation := []session.SnapshotEvent{} - for i, event := range []daemon.ProtocolEvent{ - stream("stream.text", daemon.StreamEvent{Text: "restored "}), - stream("stream.text", daemon.StreamEvent{Text: "answer"}), + for i, event := range []protocol.ProtocolEvent{ + stream("stream.text", protocol.StreamEvent{Text: "restored "}), + stream("stream.text", protocol.StreamEvent{Text: "answer"}), } { presentation = append(presentation, session.SnapshotEvent{Seq: int64(i + 1), Kind: event.Kind, Payload: event.Payload}) } @@ -801,7 +800,7 @@ func TestThinSessionPickerSwitchesBetweenPersistedModes(t *testing.T) { } raw, _ := json.Marshal(metas) _, _ = m.Update(clientCommandMsg{ - action: Action{Operation: "session.list"}, result: daemon.CommandResult{Status: "succeeded", Output: string(raw)}, + action: Action{Operation: "session.list"}, result: protocol.CommandResult{Status: "succeeded", Output: string(raw)}, }) if m.picker == nil { t.Fatal("session list did not open the daemon-backed picker") @@ -877,7 +876,7 @@ func TestThinInteractiveTerminalRestoresAndForwardsBytes(t *testing.T) { t.Cleanup(func() { _ = client.Close() }) waitClientState(t, client, ClientLive) m := &model{client: client, clientState: ClientLive, input: newInput()} - stream := func(kind string, event daemon.StreamEvent) session.SnapshotEvent { + stream := func(kind string, event protocol.StreamEvent) session.SnapshotEvent { payload, marshalErr := json.Marshal(event) if marshalErr != nil { t.Fatal(marshalErr) @@ -886,9 +885,9 @@ func TestThinInteractiveTerminalRestoresAndForwardsBytes(t *testing.T) { } m.applyClientSnapshot(session.RootSnapshot{ RootID: "root", Meta: session.Meta{ID: "root"}, Presentation: []session.SnapshotEvent{ - stream("stream.terminal.started", daemon.StreamEvent{ID: "terminal-7"}), - stream("stream.terminal.output", daemon.StreamEvent{ID: "terminal-7", Text: "Password: "}), - stream("stream.terminal.awaiting", daemon.StreamEvent{ID: "terminal-7", Text: "9"}), + stream("stream.terminal.started", protocol.StreamEvent{ID: "terminal-7"}), + stream("stream.terminal.output", protocol.StreamEvent{ID: "terminal-7", Text: "Password: "}), + stream("stream.terminal.awaiting", protocol.StreamEvent{ID: "terminal-7", Text: "9"}), }, }) if m.clientTerminalID != "terminal-7" || m.iactive == nil || m.iactive.output != "Password: " || !m.iactive.await || m.iactive.awaitcd != 9 { @@ -917,7 +916,7 @@ func TestThinInteractiveTerminalRestoresAndForwardsBytes(t *testing.T) { t.Fatalf("terminal input payload = %+v", input) } - completed := stream("stream.terminal.completed", daemon.StreamEvent{ID: "terminal-7"}) + completed := stream("stream.terminal.completed", protocol.StreamEvent{ID: "terminal-7"}) if handled, _ := m.applyClientStream(completed.Kind, completed.Payload); !handled || m.clientTerminalID != "" || m.iactive != nil { t.Fatalf("completed terminal id=%q state=%+v", m.clientTerminalID, m.iactive) } @@ -926,10 +925,10 @@ func TestThinInteractiveTerminalRestoresAndForwardsBytes(t *testing.T) { func TestClosingClientDoesNotCancelDaemonOwnedCommand(t *testing.T) { connection := newFakeDaemonConnection(session.RootSnapshot{RootID: "root", Meta: session.Meta{ID: "root"}}) started, release := make(chan struct{}), make(chan struct{}) - connection.commandFunc = func(params daemon.CommandParams) (daemon.CommandResult, error) { + connection.commandFunc = func(params protocol.CommandParams) (protocol.CommandResult, error) { close(started) <-release - return daemon.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "finished while detached"}, nil + return protocol.CommandResult{CommandID: params.CommandID, Status: "succeeded", Output: "finished while detached"}, nil } client, err := NewClient(ClientOptions{ ClientID: "tui", RootID: "root", @@ -942,7 +941,7 @@ func TestClosingClientDoesNotCancelDaemonOwnedCommand(t *testing.T) { waitClientState(t, client, ClientLive) action, _ := client.NewAction("submit", map[string]string{"text": "keep going"}) type outcome struct { - result daemon.CommandResult + result protocol.CommandResult err error } done := make(chan outcome, 1) @@ -974,16 +973,16 @@ func TestClosingClientDoesNotCancelDaemonOwnedCommand(t *testing.T) { } } -func (c *fakeDaemonConnection) Subscribe(_ context.Context, root string, cursor int64) (daemon.SubscribeResult, error) { +func (c *fakeDaemonConnection) Subscribe(_ context.Context, root string, cursor int64) (protocol.SubscribeResult, error) { c.mu.Lock() defer c.mu.Unlock() - c.subscriptions = append(c.subscriptions, daemon.SubscribeParams{RootID: root, Cursor: cursor}) - return daemon.SubscribeResult{SubscriptionID: "subscription"}, nil + c.subscriptions = append(c.subscriptions, protocol.SubscribeParams{RootID: root, Cursor: cursor}) + return protocol.SubscribeResult{SubscriptionID: "subscription"}, nil } func TestClientStreamHostEventsStayOutOfTheTranscript(t *testing.T) { m := replTestModel(t, 140) - started, _ := json.Marshal(daemon.StreamEvent{ID: "c1", InvocationID: "1:1", Name: "files.read", Args: "path=README.md"}) + started, _ := json.Marshal(protocol.StreamEvent{ID: "c1", InvocationID: "1:1", Name: "files.read", Args: "path=README.md"}) truncated, _ := json.Marshal(protocol.ContentEventPayload{ ID: "c1", InvocationID: "1:1", Name: "files.read", HostStatus: "failed", Content: protocol.ContentHandle{ReferenceID: "ref-1"}, Truncated: true, @@ -995,9 +994,9 @@ func TestClientStreamHostEventsStayOutOfTheTranscript(t *testing.T) { } // The REPL path decodes the truncated envelope's retained fields: the row // settles as failed and keeps the summary the completion dropped. - opened, _ := json.Marshal(daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code":"files.read()"}`}) + opened, _ := json.Marshal(protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code":"files.read()"}`}) for seq, event := range [][2]any{{"stream.tool.started", opened}, {"stream.cell.host.started", started}, {"stream.cell.host", truncated}} { - m.recordClientStream(daemon.ProtocolEvent{Kind: event[0].(string), Payload: event[1].([]byte), Seq: int64(seq + 1)}) + m.recordClientStream(protocol.ProtocolEvent{Kind: event[0].(string), Payload: event[1].([]byte), Seq: int64(seq + 1)}) } if got := ansi.Strip(m.replPanelView(30)); !strings.Contains(got, "→ files.read(path=README.md) ✗ failed") { t.Fatalf("truncated host completion did not settle the row:\n%s", got) @@ -1006,7 +1005,7 @@ func TestClientStreamHostEventsStayOutOfTheTranscript(t *testing.T) { func TestClientStreamHandlesEveryRegisteredKind(t *testing.T) { m := replTestModel(t, 140) - payload, _ := json.Marshal(daemon.StreamEvent{ID: "x"}) + payload, _ := json.Marshal(protocol.StreamEvent{ID: "x"}) for kind := range protocol.EventPayloads() { if strings.HasPrefix(kind, "stream.") { m.applyClientStream(kind, payload) diff --git a/internal/tui/daemon_views.go b/internal/tui/daemon_views.go index 5888a8d67..7c09662d9 100644 --- a/internal/tui/daemon_views.go +++ b/internal/tui/daemon_views.go @@ -5,12 +5,12 @@ import ( "fmt" "strings" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) func renderMCPStatus(raw string) (string, error) { - var servers []daemon.MCPStatusResult + var servers []protocol.MCPStatusResult if err := json.Unmarshal([]byte(raw), &servers); err != nil { return "", err } @@ -38,7 +38,7 @@ func renderMCPStatus(raw string) (string, error) { // cacheMCPInventory keeps the daemon's latest status rows for the MCP palette. func (m *model) cacheMCPInventory(raw string) { - var servers []daemon.MCPStatusResult + var servers []protocol.MCPStatusResult if err := json.Unmarshal([]byte(raw), &servers); err == nil { m.mcpInventory = servers } @@ -49,7 +49,7 @@ func (m *model) cacheMCPInventory(raw string) { // remote-daemon servers appear in status while a name in local config may not // be live at all. Each row offers only what the daemon can honor for that // state; blocked and unreadable rows point at the status view that says why. -func mcpPaletteRows(inventory []daemon.MCPStatusResult) []struct{ title, command string } { +func mcpPaletteRows(inventory []protocol.MCPStatusResult) []struct{ title, command string } { type row = struct{ title, command string } if len(inventory) == 0 { return []row{{"Load MCP server status (fills this list)", "/mcp status"}} @@ -77,7 +77,7 @@ func mcpPaletteRows(inventory []daemon.MCPStatusResult) []struct{ title, command } func renderLSPStatus(raw string) (string, error) { - var servers []daemon.LSPStatusResult + var servers []protocol.LSPStatusResult if err := json.Unmarshal([]byte(raw), &servers); err != nil { return "", err } @@ -114,7 +114,7 @@ func renderSchedules(raw string) (string, error) { } func renderContextAudit(raw string) (string, error) { - var audit daemon.ContextAuditResult + var audit protocol.ContextAuditResult if err := json.Unmarshal([]byte(raw), &audit); err != nil { return "", err } diff --git a/internal/tui/hit_test.go b/internal/tui/hit_test.go index db0547093..30573d890 100644 --- a/internal/tui/hit_test.go +++ b/internal/tui/hit_test.go @@ -6,10 +6,10 @@ import ( "testing" "charm.land/lipgloss/v2" - uv "github.com/charmbracelet/ultraviolet" + "github.com/context-labs/whip/internal/protocol" + uv "github.com/charmbracelet/ultraviolet" "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/session" ) @@ -87,7 +87,7 @@ func TestLayoutFrameOracle(t *testing.T) { {"thought", func(m *model) { m.curThink = "considering the options" }}, {"current", func(m *model) { m.current = "streaming partial answer" }}, {"plan", func(m *model) { - m.plan = []daemon.PlanItem{{Content: "one", Status: "pending"}, {Content: "two", Status: "done"}} + m.plan = []protocol.PlanItem{{Content: "one", Status: "pending"}, {Content: "two", Status: "done"}} }}, {"permission", func(m *model) { m.permDialog = &permDialog{daemon: &session.PermissionSnapshot{ID: "p1", Rule: "x"}} }}, {"interactive", func(m *model) { m.iactive = &interactive{output: "$ ls\nfoo\n"} }}, @@ -252,7 +252,7 @@ func TestLayoutRectsPartitionMainColumn(t *testing.T) { {"rewind", func(m *model) { m.rew = &rewindState{entries: []rewindEntry{{cut: 0, text: "x"}}} }}, {"name-prompt", func(m *model) { m.openNamePrompt("name:", "", func(string) {}) }}, {"tall-input", func(m *model) { m.input.SetValue("one\ntwo\nthree\nfour") }}, - {"plan", func(m *model) { m.plan = []daemon.PlanItem{{Content: "one", Status: "pending"}} }}, + {"plan", func(m *model) { m.plan = []protocol.PlanItem{{Content: "one", Status: "pending"}} }}, {"permission", func(m *model) { m.permDialog = &permDialog{daemon: &session.PermissionSnapshot{ID: "p1", Rule: "x"}} }}, {"interactive", func(m *model) { m.iactive = &interactive{output: "$ ls\nfoo\n"} }}, } { diff --git a/internal/tui/mcp_palette_test.go b/internal/tui/mcp_palette_test.go index fe0433205..f2b1a23d8 100644 --- a/internal/tui/mcp_palette_test.go +++ b/internal/tui/mcp_palette_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/context-labs/whip/internal/daemon" + "github.com/context-labs/whip/internal/protocol" ) // TestMCPPaletteRowsFollowDaemonState: rows offer only what the daemon can @@ -14,7 +14,7 @@ func TestMCPPaletteRowsFollowDaemonState(t *testing.T) { if len(empty) != 1 || empty[0].command != "/mcp status" { t.Fatalf("empty inventory rows = %+v", empty) } - rows := mcpPaletteRows([]daemon.MCPStatusResult{ + rows := mcpPaletteRows([]protocol.MCPStatusResult{ {Name: "docs", Status: "ready"}, {Name: "slow", Status: "connecting"}, {Name: "off", Status: "disabled"}, diff --git a/internal/tui/menu_key_test.go b/internal/tui/menu_key_test.go index 38d3a9a9b..7c5f7d1a3 100644 --- a/internal/tui/menu_key_test.go +++ b/internal/tui/menu_key_test.go @@ -3,9 +3,9 @@ package tui import ( "testing" - tea "charm.land/bubbletea/v2" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" + + tea "charm.land/bubbletea/v2" ) func pressKey(m *model, kt rune) *model { return pressMsg(m, keyMsg(kt)) } @@ -22,7 +22,7 @@ func TestTabCompletesSkillName(t *testing.T) { m = typeStr(t, m, "$go-sty") request := &clientCompletion{value: m.input.Value(), rootID: m.sessionID, agentID: m.agentOpen} m.hostCompletion = request - m.applyHostCompletion(clientCompletionMsg{request: request, result: daemon.CompletionResult{Candidates: []protocol.CompletionCandidate{{Text: "$go-style", Description: "d"}}}}) + m.applyHostCompletion(clientCompletionMsg{request: request, result: protocol.CompletionResult{Candidates: []protocol.CompletionCandidate{{Text: "$go-style", Description: "d"}}}}) if m.menu == nil || len(m.menu.cands) != 1 || m.menu.cands[0].Text != "$go-style" { t.Fatalf("menu should hold exactly $go-style: %+v", m.menu) } diff --git a/internal/tui/model_accounting_test.go b/internal/tui/model_accounting_test.go index 4a01dd6e6..23eae56de 100644 --- a/internal/tui/model_accounting_test.go +++ b/internal/tui/model_accounting_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -31,7 +31,7 @@ func TestModelAccountingUsesDurableTreeChargesAndShowsUncertainty(t *testing.T) m.agentOpen = "child" a.ReportedCostMicros = 0 a.Revision = 10 - payload, err := json.Marshal(daemon.StreamEvent{Accounting: &a}) + payload, err := json.Marshal(protocol.StreamEvent{Accounting: &a}) if err != nil { t.Fatal(err) } @@ -44,7 +44,7 @@ func TestModelAccountingUsesDurableTreeChargesAndShowsUncertainty(t *testing.T) func TestModelAccountingIgnoresOlderQueuedSummary(t *testing.T) { m := model{} m.clientView.accounting = session.ModelAccounting{RootID: "root", Revision: 20, ReportedCostMicros: 300} - payload, err := json.Marshal(daemon.StreamEvent{Accounting: &session.ModelAccounting{RootID: "root", Revision: 19, ReportedCostMicros: 100}}) + payload, err := json.Marshal(protocol.StreamEvent{Accounting: &session.ModelAccounting{RootID: "root", Revision: 19, ReportedCostMicros: 100}}) if err != nil { t.Fatal(err) } diff --git a/internal/tui/opencode_client_test.go b/internal/tui/opencode_client_test.go index 679fea179..c914fbd66 100644 --- a/internal/tui/opencode_client_test.go +++ b/internal/tui/opencode_client_test.go @@ -5,12 +5,12 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" ) func TestFullScreenLayoutFitsTerminal(t *testing.T) { @@ -73,7 +73,7 @@ func TestOpencodeDialogsUseRecursiveCommandSurface(t *testing.T) { } // Server rows come from the daemon's inventory, not local config: the // config's "local" is stale here and must not appear; the daemon's rows do. - m.mcpInventory = []daemon.MCPStatusResult{{Name: "docs", Status: "ready", Tools: 3}, {Name: "ghost", Status: "blocked", Note: "blocked by mcpImport config (project)"}} + m.mcpInventory = []protocol.MCPStatusResult{{Name: "docs", Status: "ready", Tools: 3}, {Name: "ghost", Status: "blocked", Note: "blocked by mcpImport config (project)"}} m.openThinMCPPalette() out = strings.Join(m.ocDialogRows(), "\n") for _, want := range []string{"MCP import status", "Enable Codex imports", "Enable project .mcp.json imports", "Reconnect docs", "Disable docs for this session", "Why is ghost blocked"} { diff --git a/internal/tui/paste_chip_test.go b/internal/tui/paste_chip_test.go index 109830547..c8dad7a5e 100644 --- a/internal/tui/paste_chip_test.go +++ b/internal/tui/paste_chip_test.go @@ -8,10 +8,10 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" - - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/session" ) @@ -198,7 +198,7 @@ func TestClearResetsImageRegistry(t *testing.T) { m := compactCmdModel() m.images, m.imageSeq = []pastedImage{{n: 1, path: "/p/a.png"}}, 1 chip := m.images[0].chipText() - tm, _ := m.Update(clientCommandMsg{action: Action{Operation: "history.clear"}, result: daemon.CommandResult{Status: "succeeded"}}) + tm, _ := m.Update(clientCommandMsg{action: Action{Operation: "history.clear"}, result: protocol.CommandResult{Status: "succeeded"}}) m = tm.(*model) if len(m.images) != 0 || m.imageSeq != 0 { t.Fatalf("clear left registry: images=%d imageSeq=%d", len(m.images), m.imageSeq) @@ -212,7 +212,7 @@ func TestClearResetsImageRegistry(t *testing.T) { func TestFailedClearKeepsImageRegistry(t *testing.T) { m := compactCmdModel() m.images, m.imageSeq = []pastedImage{{n: 1, path: "/p/a.png"}}, 1 - tm, _ := m.Update(clientCommandMsg{action: Action{Operation: "history.clear"}, result: daemon.CommandResult{Error: "busy"}}) + tm, _ := m.Update(clientCommandMsg{action: Action{Operation: "history.clear"}, result: protocol.CommandResult{Error: "busy"}}) m = tm.(*model) if len(m.images) != 1 || m.imageSeq != 1 { t.Fatalf("failed clear touched registry: images=%d imageSeq=%d", len(m.images), m.imageSeq) diff --git a/internal/tui/question_test.go b/internal/tui/question_test.go index e62cb01e8..f81594d0b 100644 --- a/internal/tui/question_test.go +++ b/internal/tui/question_test.go @@ -6,12 +6,11 @@ import ( "strings" "testing" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" "github.com/charmbracelet/x/exp/golden" - - "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -63,7 +62,7 @@ func sentAnswer(t *testing.T, command tea.Cmd) questionAnswer { } // answerReply is the daemon's reply to our own question.answer for payload. -func answerReply(payload string, result daemon.CommandResult, err error) clientCommandMsg { +func answerReply(payload string, result protocol.CommandResult, err error) clientCommandMsg { return clientCommandMsg{action: Action{Operation: "question.answer", Payload: json.RawMessage(payload)}, result: result, err: err} } @@ -158,7 +157,7 @@ func TestQuestionSingleKeysMoveJumpAndAnswer(t *testing.T) { t.Fatal("hints do not say sending…") } // the reply closes the dialog and writes the line; the event that follows adds nothing - m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, daemon.CommandResult{Status: "succeeded", Output: "answered"}, nil)) + m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, protocol.CommandResult{Status: "succeeded", Output: "answered"}, nil)) if m.question != nil { t.Fatal("the succeeded reply did not close the dialog") } @@ -202,7 +201,7 @@ func TestQuestionEscDismisses(t *testing.T) { // the event lands first here; the reply that follows adds nothing payload, _ := json.Marshal(session.LifecycleEvent{QuestionID: "q1", Dismissed: true}) m.applyClientLifecycle("question.answered", payload) - m.Update(answerReply(`{"id":"q1","dismissed":true}`, daemon.CommandResult{Status: "succeeded", Output: "dismissed"}, nil)) + m.Update(answerReply(`{"id":"q1","dismissed":true}`, protocol.CommandResult{Status: "succeeded", Output: "dismissed"}, nil)) if m.question != nil || strings.Count(m.transcriptText(), `" dismissed)`) != 1 { t.Fatalf("dialog=%v transcript=%q", m.question != nil, m.transcriptText()) } @@ -293,17 +292,17 @@ func TestQuestionAnswerFailures(t *testing.T) { q := openQuestion(t, m, questionPending(false)) q.inFlight = true // replies for a question that closed meanwhile leave the dialog now open alone - m.Update(answerReply(`{"id":"q-old","answer":["x"]}`, daemon.CommandResult{Status: "failed", Error: `question "q-old" is not open`}, nil)) - m.Update(answerReply(`{"id":"q-old","answer":["x"]}`, daemon.CommandResult{}, errors.New("socket closed"))) + m.Update(answerReply(`{"id":"q-old","answer":["x"]}`, protocol.CommandResult{Status: "failed", Error: `question "q-old" is not open`}, nil)) + m.Update(answerReply(`{"id":"q-old","answer":["x"]}`, protocol.CommandResult{}, errors.New("socket closed"))) if m.question != q || !q.inFlight { t.Fatalf("another question's reply touched the dialog: dialog=%v inFlight=%v", m.question == q, q.inFlight) } - m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, daemon.CommandResult{}, errors.New("socket closed"))) + m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, protocol.CommandResult{}, errors.New("socket closed"))) if m.question != q || q.inFlight || !strings.Contains(m.transcriptText(), "socket closed") { t.Fatalf("transport failure: dialog=%v inFlight=%v transcript=%q", m.question == q, q.inFlight, m.transcriptText()) } q.inFlight = true - m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, daemon.CommandResult{Status: "failed", Error: "unknown question q1"}, nil)) + m.Update(answerReply(`{"id":"q1","answer":["bun"]}`, protocol.CommandResult{Status: "failed", Error: "unknown question q1"}, nil)) if m.question != nil || !strings.Contains(m.transcriptText(), "unknown question q1") { t.Fatalf("daemon rejection: dialog=%v transcript=%q", m.question != nil, m.transcriptText()) } diff --git a/internal/tui/repl_panel.go b/internal/tui/repl_panel.go index c161e3f72..d6b8d4c7f 100644 --- a/internal/tui/repl_panel.go +++ b/internal/tui/repl_panel.go @@ -10,14 +10,13 @@ import ( "time" "unicode" + "charm.land/lipgloss/v2" + "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/tui/theme" "github.com/context-labs/whip/internal/tui/ui" - "charm.land/lipgloss/v2" uv "github.com/charmbracelet/ultraviolet" "github.com/charmbracelet/x/ansi" - - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/session" ) @@ -88,7 +87,7 @@ func (m *model) replNow() time.Time { // replApplySeq folds an event with a known sequence number, skipping ones // already seen: live events and later snapshot replays carry the same seq. -func (m *model) replApplySeq(agentID, kind string, event daemon.StreamEvent, seq int64) { +func (m *model) replApplySeq(agentID, kind string, event protocol.StreamEvent, seq int64) { if seq > 0 { agent := m.replAgentFor(agentID) if seq <= agent.seq { @@ -100,7 +99,7 @@ func (m *model) replApplySeq(agentID, kind string, event daemon.StreamEvent, seq } // replApply folds one presentation event into an agent's cell history. -func (m *model) replApply(agentID, kind string, event daemon.StreamEvent) { +func (m *model) replApply(agentID, kind string, event protocol.StreamEvent) { if event.ID == "" { return } @@ -248,7 +247,7 @@ func (m *model) replRebuild() { if !strings.HasPrefix(event.Kind, "stream.") { continue } - var payload daemon.StreamEvent + var payload protocol.StreamEvent if json.Unmarshal(event.Payload, &payload) != nil { continue } diff --git a/internal/tui/repl_panel_test.go b/internal/tui/repl_panel_test.go index 0c9bca09f..5dd1dba50 100644 --- a/internal/tui/repl_panel_test.go +++ b/internal/tui/repl_panel_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/session" ) @@ -50,20 +50,20 @@ func TestReplReducerBuildsCellsAndPanelRenders(t *testing.T) { if m.panelWidth() != (140-opencodeLeftMargin)/2 || m.leftVisible() { t.Fatalf("panel width = %d left=%v (the REPL displaces the left column below %d columns and takes half the terminal)", m.panelWidth(), m.leftVisible(), replMinWide) } - m.replApply("root-agent", "stream.tool.call", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f`}) - m.replApply("root-agent", "stream.tool.call", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f)"}`}) - m.replApply("root-agent", "stream.tool.started", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f)"}`}) - m.replApply("root-agent", "stream.cell.host", daemon.StreamEvent{ID: "c1", Name: "files.list", Args: "path=.", Text: "12ms"}) - m.replApply("root-agent", "stream.tool.output", daemon.StreamEvent{ID: "c1", Text: "a.go\n"}) - m.replApply("child", "stream.tool.call", daemon.StreamEvent{ID: "k1", Name: "rlm_exec", Args: `{"code": "shell.run(command=\"sleep 5\")"}`}) - m.replApply("child", "stream.tool.started", daemon.StreamEvent{ID: "k1", Name: "rlm_exec", Args: `{"code": "shell.run(command=\"sleep 5\")"}`}) + m.replApply("root-agent", "stream.tool.call", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f`}) + m.replApply("root-agent", "stream.tool.call", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f)"}`}) + m.replApply("root-agent", "stream.tool.started", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Args: `{"code": "for f in files.list(path=\".\"):\n print(f)"}`}) + m.replApply("root-agent", "stream.cell.host", protocol.StreamEvent{ID: "c1", Name: "files.list", Args: "path=.", Text: "12ms"}) + m.replApply("root-agent", "stream.tool.output", protocol.StreamEvent{ID: "c1", Text: "a.go\n"}) + m.replApply("child", "stream.tool.call", protocol.StreamEvent{ID: "k1", Name: "rlm_exec", Args: `{"code": "shell.run(command=\"sleep 5\")"}`}) + m.replApply("child", "stream.tool.started", protocol.StreamEvent{ID: "k1", Name: "rlm_exec", Args: `{"code": "shell.run(command=\"sleep 5\")"}`}) running := m.replPanelView(30) for _, want := range []string{"REPL · root", "1 cell", "In [1]", "files.list", "→ files.list(path=.) 12ms", "a.go"} { if !strings.Contains(running, want) { t.Fatalf("running panel missing %q:\n%s", want, running) } } - m.replApply("root-agent", "stream.tool.completed", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":3,"output":"a.go\nb.go\n","steps":42}`}) + m.replApply("root-agent", "stream.tool.completed", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":3,"output":"a.go\nb.go\n","steps":42}`}) m.replRestart("root-agent", 9, 1) done := m.replPanelView(30) for _, want := range []string{"42 steps", "b.go", "⇒ ", "restarted · restored 9 · 1 skipped"} { @@ -82,7 +82,7 @@ func TestReplReducerBuildsCellsAndPanelRenders(t *testing.T) { t.Fatalf("panel row contains a replacement character: %q", ansi.Strip(line)) } } - m.replApply("root-agent", "stream.tool.completed", daemon.StreamEvent{ID: "c2", Name: "rlm_exec", Result: "Error: <rlm-cell>:1:1: undefined: nope"}) + m.replApply("root-agent", "stream.tool.completed", protocol.StreamEvent{ID: "c2", Name: "rlm_exec", Result: "Error: <rlm-cell>:1:1: undefined: nope"}) if failed := m.replPanelView(30); !strings.Contains(failed, "✗ <rlm-cell>:1:1: undefined: nope") || !strings.Contains(failed, "In [2]") { t.Fatalf("failed cell not rendered:\n%s", failed) } @@ -126,13 +126,13 @@ func TestReplPanelToggleChordAndCommand(t *testing.T) { func TestReplRebuildsFromStoredPresentation(t *testing.T) { m := replTestModel(t, 140) - encode := func(event daemon.StreamEvent) []byte { + encode := func(event protocol.StreamEvent) []byte { payload, _ := json.Marshal(event) return payload } m.clientView.agentPresentations = map[string][]session.SnapshotEvent{"child": { - {Seq: 1, Kind: "stream.tool.started", Payload: encode(daemon.StreamEvent{AgentID: "child", ID: "k1", Name: "rlm_exec", Args: `{"code": "memo = 1"}`})}, - {Seq: 2, Kind: "stream.tool.completed", Payload: encode(daemon.StreamEvent{AgentID: "child", ID: "k1", Name: "rlm_exec", Result: `{"value":null,"steps":3}`})}, + {Seq: 1, Kind: "stream.tool.started", Payload: encode(protocol.StreamEvent{AgentID: "child", ID: "k1", Name: "rlm_exec", Args: `{"code": "memo = 1"}`})}, + {Seq: 2, Kind: "stream.tool.completed", Payload: encode(protocol.StreamEvent{AgentID: "child", ID: "k1", Name: "rlm_exec", Result: `{"value":null,"steps":3}`})}, }} m.agentOpen = "child" m.replRebuild() @@ -146,8 +146,8 @@ func TestReplPanelScrollsIndependentlyOfChat(t *testing.T) { for i := 1; i <= 30; i++ { id := fmt.Sprintf("call-%d", i) args := fmt.Sprintf(`{"code":"x = %d"}`, i) - m.replApply("root-agent", "stream.tool.started", daemon.StreamEvent{ID: id, Name: "rlm_exec", Args: args}) - m.replApply("root-agent", "stream.tool.completed", daemon.StreamEvent{ID: id, Name: "rlm_exec", Result: `{"value":1}`}) + m.replApply("root-agent", "stream.tool.started", protocol.StreamEvent{ID: id, Name: "rlm_exec", Args: args}) + m.replApply("root-agent", "stream.tool.completed", protocol.StreamEvent{ID: id, Name: "rlm_exec", Result: `{"value":1}`}) } view := m.replPanelView(20) if !strings.Contains(view, "In [30]") || strings.Contains(view, "In [1]") { @@ -228,15 +228,15 @@ func TestReplHistorySurvivesSnapshotsAndKeepsScroll(t *testing.T) { m := replTestModel(t, 140) clock := time.Date(2026, 9, 3, 12, 0, 0, 0, time.UTC) m.now = func() time.Time { return clock } - encode := func(event daemon.StreamEvent) []byte { + encode := func(event protocol.StreamEvent) []byte { payload, _ := json.Marshal(event) return payload } var seq int64 cellEvents := func(i int) []session.SnapshotEvent { id := fmt.Sprintf("call-%d", i) - started := daemon.StreamEvent{ID: id, Name: "rlm_exec", Args: fmt.Sprintf(`{"code":"x = %d"}`, i)} - completed := daemon.StreamEvent{ID: id, Name: "rlm_exec", Result: `{"value":1,"steps":2}`} + started := protocol.StreamEvent{ID: id, Name: "rlm_exec", Args: fmt.Sprintf(`{"code":"x = %d"}`, i)} + completed := protocol.StreamEvent{ID: id, Name: "rlm_exec", Result: `{"value":1,"steps":2}`} seq += 2 return []session.SnapshotEvent{ {Seq: seq - 1, Kind: "stream.tool.started", Payload: encode(started)}, @@ -253,14 +253,14 @@ func TestReplHistorySurvivesSnapshotsAndKeepsScroll(t *testing.T) { t.Fatalf("replayed cells must render without a fabricated duration:\n%s", view) } // A live cell (recordClientStream path) keeps its measured duration across later snapshots. - live := func(kind string, event daemon.StreamEvent) { + live := func(kind string, event protocol.StreamEvent) { seq++ payload := encode(event) - m.recordClientStream(daemon.ProtocolEvent{Seq: seq, Kind: kind, Payload: payload}) + m.recordClientStream(protocol.ProtocolEvent{Seq: seq, Kind: kind, Payload: payload}) } - live("stream.tool.started", daemon.StreamEvent{ID: "call-31", Name: "rlm_exec", Args: `{"code":"x = 31"}`}) + live("stream.tool.started", protocol.StreamEvent{ID: "call-31", Name: "rlm_exec", Args: `{"code":"x = 31"}`}) clock = clock.Add(2 * time.Second) - live("stream.tool.completed", daemon.StreamEvent{ID: "call-31", Name: "rlm_exec", Result: `{"value":1}`}) + live("stream.tool.completed", protocol.StreamEvent{ID: "call-31", Name: "rlm_exec", Result: `{"value":1}`}) if view = m.replPanelView(20); !strings.Contains(view, "In [31] 2.0s") { t.Fatalf("live cell duration missing:\n%s", view) } @@ -286,14 +286,14 @@ func TestReplHistorySurvivesSnapshotsAndKeepsScroll(t *testing.T) { t.Fatalf("replayed snapshot duplicated cells: %d", got) } // New rows arriving below keep the scrolled-up content anchored. - live("stream.tool.started", daemon.StreamEvent{ID: "call-32", Name: "rlm_exec", Args: `{"code":"x = 32"}`}) + live("stream.tool.started", protocol.StreamEvent{ID: "call-32", Name: "rlm_exec", Args: `{"code":"x = 32"}`}) after := m.replPanelView(20) beforeRows, afterRows := strings.Split(before, "\n"), strings.Split(after, "\n") if m.replScroll <= 15 || beforeRows[6] != afterRows[6] || beforeRows[10] != afterRows[10] { t.Fatalf("new rows shifted the scrolled view (scroll=%d)\nbefore:\n%s\nafter:\n%s", m.replScroll, before, after) } // An idle child's cells stay visible even though snapshots drop them. - m.recordClientStream(daemon.ProtocolEvent{Seq: seq + 1, Kind: "stream.tool.started", Payload: encode(daemon.StreamEvent{AgentID: "child", ID: "c-1", Name: "rlm_exec", Args: `{"code":"y = 1"}`})}) + m.recordClientStream(protocol.ProtocolEvent{Seq: seq + 1, Kind: "stream.tool.started", Payload: encode(protocol.StreamEvent{AgentID: "child", ID: "c-1", Name: "rlm_exec", Args: `{"code":"y = 1"}`})}) m.clientView.agentPresentations = nil m.replRebuild() m.agentOpen = "child" @@ -373,9 +373,9 @@ func TestReplPanelKeepsRowsOnOneLineAndWrapsCodeLosslessly(t *testing.T) { m := replTestModel(t, 140) code := "x = \"" + strings.Repeat("a", 200) + "\"\n\tif x:\n\t\tprint(x)" args, _ := json.Marshal(map[string]string{"code": code}) - m.replApply("root-agent", "stream.tool.started", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Args: string(args)}) - m.replApply("root-agent", "stream.cell.host", daemon.StreamEvent{ID: "c1", Name: "shell.run", Args: "command=a\tb\nc\r", Text: "1ms", Result: "boom\nline two"}) - m.replApply("root-agent", "stream.tool.completed", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":"v\tw\nz","output":"col1\tcol2\r\nnext"}`}) + m.replApply("root-agent", "stream.tool.started", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Args: string(args)}) + m.replApply("root-agent", "stream.cell.host", protocol.StreamEvent{ID: "c1", Name: "shell.run", Args: "command=a\tb\nc\r", Text: "1ms", Result: "boom\nline two"}) + m.replApply("root-agent", "stream.tool.completed", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":"v\tw\nz","output":"col1\tcol2\r\nnext"}`}) view := m.replPanelView(40) rows := strings.Split(view, "\n") if len(rows) != 40 { @@ -429,11 +429,11 @@ func TestAgentDetailsFitTheChatColumn(t *testing.T) { func TestReplHostLifecycle(t *testing.T) { m := replTestModel(t, 140) cell := func(id, code string) { - m.replApply("root-agent", "stream.tool.call", daemon.StreamEvent{ID: id, Name: "rlm_exec", Args: `{"code": "` + code + `"}`}) - m.replApply("root-agent", "stream.tool.started", daemon.StreamEvent{ID: id, Name: "rlm_exec", Args: `{"code": "` + code + `"}`}) + m.replApply("root-agent", "stream.tool.call", protocol.StreamEvent{ID: id, Name: "rlm_exec", Args: `{"code": "` + code + `"}`}) + m.replApply("root-agent", "stream.tool.started", protocol.StreamEvent{ID: id, Name: "rlm_exec", Args: `{"code": "` + code + `"}`}) } host := func(kind, invocation, name, status, duration, result string) { - m.replApply("root-agent", kind, daemon.StreamEvent{ID: "c1", InvocationID: invocation, Name: name, Args: "path=README.md", HostStatus: status, Text: duration, Result: result}) + m.replApply("root-agent", kind, protocol.StreamEvent{ID: "c1", InvocationID: invocation, Name: name, Args: "path=README.md", HostStatus: status, Text: duration, Result: result}) } view := func() string { return ansi.Strip(m.replPanelView(30)) } expect := func(what string, want ...string) { @@ -464,7 +464,7 @@ func TestReplHostLifecycle(t *testing.T) { host("stream.cell.host", "1:4", "files.write", "failed", "3s", "") // the daemon truncated the error away host("stream.cell.host", "", "context.read", "", "4ms", "") // completion-only history from an older daemon host("stream.cell.host.started", "1:5", "agents.wait", "", "", "") - m.replApply("root-agent", "stream.tool.completed", daemon.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":null,"output":"","steps":5}`}) + m.replApply("root-agent", "stream.tool.completed", protocol.StreamEvent{ID: "c1", Name: "rlm_exec", Result: `{"value":null,"output":"","steps":5}`}) expect("outcomes", "→ shell.run(path=README.md) ✗ boom", "→ shell.run(path=README.md) cancelled", @@ -486,7 +486,7 @@ func TestReplHostLifecycle(t *testing.T) { } // A long summary is clipped before the status, never instead of it. - m.replApply("root-agent", "stream.cell.host", daemon.StreamEvent{ID: "c1", InvocationID: "2:1", Name: "files.list", Args: strings.Repeat("path=very/long/", 20), HostStatus: "completed", Text: "12ms"}) + m.replApply("root-agent", "stream.cell.host", protocol.StreamEvent{ID: "c1", InvocationID: "2:1", Name: "files.list", Args: strings.Repeat("path=very/long/", 20), HostStatus: "completed", Text: "12ms"}) for line := range strings.SplitSeq(view(), "\n") { if !strings.Contains(line, "→ files.list") { continue diff --git a/internal/tui/setup.go b/internal/tui/setup.go index 1a8f62920..09f2af5aa 100644 --- a/internal/tui/setup.go +++ b/internal/tui/setup.go @@ -8,13 +8,12 @@ import ( "time" "charm.land/bubbles/v2/textinput" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/tui/ui" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/protocol" + "github.com/context-labs/whip/internal/tui/ui" ) var errProviderReadinessUnavailable = errors.New("this execution host cannot report provider readiness; update Whip on the host and restart it, then reconnect") @@ -36,7 +35,7 @@ type providerSetup struct { model, provider string list protocol.ProviderList catalogs protocol.ProviderCatalogsResult - login daemon.ProviderLoginStatus + login protocol.ProviderLoginStatus loginFeedback string openedURL string mode string @@ -64,7 +63,7 @@ type setupReply struct { kind string list protocol.ProviderList catalogs protocol.ProviderCatalogsResult - login daemon.ProviderLoginStatus + login protocol.ProviderLoginStatus err error configuration protocol.ProviderConfiguration model string @@ -348,7 +347,7 @@ func (s *providerSetup) connectMethod(entry protocol.ProviderEntry, method strin s.provider, s.model, s.effort, s.selected = entry.ID, "", "", 0 s.autoModel = false s.notice, s.message, s.loginFeedback = "", "", "" - s.login, s.openedURL = daemon.ProviderLoginStatus{}, "" + s.login, s.openedURL = protocol.ProviderLoginStatus{}, "" s.pickKey = false s.input.Reset() s.input.EchoMode = textinput.EchoNormal @@ -385,7 +384,7 @@ func setupLoginActive(state string) bool { return state != "succeeded" && state != "failed" && state != "expired" && state != "cancelled" && state != "interrupted" } -func (s *providerSetup) applyLogin(status daemon.ProviderLoginStatus) tea.Cmd { +func (s *providerSetup) applyLogin(status protocol.ProviderLoginStatus) tea.Cmd { s.login = status if status.VerificationURL != "" && s.openedURL != status.VerificationURL { s.openedURL = status.VerificationURL @@ -423,7 +422,7 @@ func (s *providerSetup) poll() tea.Cmd { func (s *providerSetup) chooseLogin(choice string, project bool) tea.Cmd { host, id := s.host, s.login.FlowID return s.call("login", func(ctx context.Context) setupReply { - var status daemon.ProviderLoginStatus + var status protocol.ProviderLoginStatus var err error if project { status, err = host.SelectLoginProject(ctx, id, choice) @@ -451,7 +450,7 @@ func (s *providerSetup) useModel() tea.Cmd { if !persist { return setupReply{} } - _, err := host.UpdateConfiguration(ctx, daemon.ConfigurationUpdate{ + _, err := host.UpdateConfiguration(ctx, protocol.ConfigurationUpdate{ Revision: revision, DefaultModel: &model, DefaultProvider: &provider, DefaultEffort: effort, }) @@ -598,7 +597,7 @@ func (s *providerSetup) keypress(msg tea.KeyPressMsg) tea.Cmd { } host, revision, provider := s.host, s.list.Revision, s.provider return s.call("key", func(ctx context.Context) setupReply { - _, err := host.SetProviderKey(ctx, daemon.ProviderKeySetup{Revision: revision, Provider: provider, Key: key}) + _, err := host.SetProviderKey(ctx, protocol.ProviderKeySetup{Revision: revision, Provider: provider, Key: key}) return setupReply{err: err} }) case "teams": diff --git a/internal/tui/setup_default_test.go b/internal/tui/setup_default_test.go index fbaa406f4..b4271d865 100644 --- a/internal/tui/setup_default_test.go +++ b/internal/tui/setup_default_test.go @@ -7,7 +7,6 @@ import ( "github.com/charmbracelet/x/ansi" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" ) @@ -57,7 +56,7 @@ func TestSetupProviderDefaultsCloseWithoutModelConfirmation(t *testing.T) { providerFormDrain(t, s, s.keypress(setupKey("enter"))) case "login": entry.Status.Available = new(true) - providerFormDrain(t, s, s.applyLogin(daemon.ProviderLoginStatus{State: "succeeded"})) + providerFormDrain(t, s, s.applyLogin(protocol.ProviderLoginStatus{State: "succeeded"})) } if !s.done || !s.chosen || s.model != tc.model || s.provider != tc.provider || s.effort != tc.effort || s.message != "" { t.Fatalf("selection=%s/%s/%s done=%v message=%q", s.provider, s.model, s.effort, s.done, s.message) diff --git a/internal/tui/setup_host.go b/internal/tui/setup_host.go index a991f7e67..09d043cda 100644 --- a/internal/tui/setup_host.go +++ b/internal/tui/setup_host.go @@ -3,27 +3,26 @@ package tui import ( "context" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" ) type setupHost interface { - ReadConfiguration(context.Context) (daemon.RuntimeConfiguration, error) - UpdateConfiguration(context.Context, daemon.ConfigurationUpdate) (daemon.RuntimeConfiguration, error) + ReadConfiguration(context.Context) (protocol.RuntimeConfiguration, error) + UpdateConfiguration(context.Context, protocol.ConfigurationUpdate) (protocol.RuntimeConfiguration, error) ReadProvider(context.Context, string) (protocol.ProviderConfiguration, error) CreateProvider(context.Context, protocol.ProviderCreateParams) (protocol.ProviderConfiguration, error) UpdateProvider(context.Context, protocol.ProviderUpdateParams) (protocol.ProviderConfiguration, error) RemoveProvider(context.Context, protocol.ProviderRemoveParams) (protocol.ProviderRemoveResult, error) DisconnectProvider(context.Context, protocol.ProviderDisconnectParams) (protocol.ProviderStatus, error) - SetProviderKey(context.Context, daemon.ProviderKeySetup) (daemon.RuntimeConfiguration, error) + SetProviderKey(context.Context, protocol.ProviderKeySetup) (protocol.RuntimeConfiguration, error) ListProvidersFor(context.Context, string, string) (protocol.ProviderList, error) DiscoverProviders(context.Context, string, string) (protocol.ProviderList, error) ProviderCatalogsFor(context.Context, string, bool) (protocol.ProviderCatalogsResult, error) - ListLogins(context.Context) (daemon.ProviderLoginList, error) - BeginProviderLogin(context.Context, string) (daemon.ProviderLoginStatus, error) - CancelLogin(context.Context, string) (daemon.ProviderLoginStatus, error) - LoginStatus(context.Context, string) (daemon.ProviderLoginStatus, error) - SelectLoginTeam(context.Context, string, string) (daemon.ProviderLoginStatus, error) - SelectLoginProject(context.Context, string, string) (daemon.ProviderLoginStatus, error) - CreateLoginProject(context.Context, string, string) (daemon.ProviderLoginStatus, error) + ListLogins(context.Context) (protocol.ProviderLoginList, error) + BeginProviderLogin(context.Context, string) (protocol.ProviderLoginStatus, error) + CancelLogin(context.Context, string) (protocol.ProviderLoginStatus, error) + LoginStatus(context.Context, string) (protocol.ProviderLoginStatus, error) + SelectLoginTeam(context.Context, string, string) (protocol.ProviderLoginStatus, error) + SelectLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) + CreateLoginProject(context.Context, string, string) (protocol.ProviderLoginStatus, error) } diff --git a/internal/tui/setup_provider.go b/internal/tui/setup_provider.go index 560d99566..74e599270 100644 --- a/internal/tui/setup_provider.go +++ b/internal/tui/setup_provider.go @@ -9,10 +9,10 @@ import ( "strings" "charm.land/bubbles/v2/textinput" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/tui/ui" ) @@ -503,7 +503,7 @@ func (s *providerSetup) setProviderDisabled(disabled bool) tea.Cmd { if disabled { providers = append(providers, provider) } - _, err = host.UpdateConfiguration(ctx, daemon.ConfigurationUpdate{Revision: revision, DisabledProviders: &providers}) + _, err = host.UpdateConfiguration(ctx, protocol.ConfigurationUpdate{Revision: revision, DisabledProviders: &providers}) return setupReply{err: err} }) } diff --git a/internal/tui/setup_provider_test.go b/internal/tui/setup_provider_test.go index f5789331e..963e12c5d 100644 --- a/internal/tui/setup_provider_test.go +++ b/internal/tui/setup_provider_test.go @@ -9,11 +9,11 @@ import ( "strings" "testing" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" ) @@ -90,8 +90,8 @@ func (h *providerFormHost) RemoveProvider(_ context.Context, p protocol.Provider return protocol.ProviderRemoveResult{Revision: "removed"}, h.err } -func (h *providerFormHost) ReadConfiguration(context.Context) (daemon.RuntimeConfiguration, error) { - return daemon.RuntimeConfiguration{Revision: h.view.Revision, DisabledProviders: new([]string{"unrelated"})}, nil +func (h *providerFormHost) ReadConfiguration(context.Context) (protocol.RuntimeConfiguration, error) { + return protocol.RuntimeConfiguration{Revision: h.view.Revision, DisabledProviders: new([]string{"unrelated"})}, nil } func providerFormKey(key string) tea.KeyPressMsg { @@ -807,7 +807,7 @@ func TestSetupProviderBrowserReloginReloadsCurrentPairAfterSelection(t *testing. h.list.Providers[0].SuggestedModel = "coding-model" _, cmd := s.Update(setupReply{ owner: s, request: s.request, kind: "login", - login: daemon.ProviderLoginStatus{Provider: "inference-net", FlowID: "replacement-login", State: "succeeded"}, + login: protocol.ProviderLoginStatus{Provider: "inference-net", FlowID: "replacement-login", State: "succeeded"}, }) providerFormDrain(t, s, cmd) if s.mode != "models" || s.provider != "inference-net" || s.model != "coding-model" || s.done || len(h.writes) != 0 { diff --git a/internal/tui/setup_test.go b/internal/tui/setup_test.go index f3109cff4..30d19599a 100644 --- a/internal/tui/setup_test.go +++ b/internal/tui/setup_test.go @@ -7,18 +7,18 @@ import ( "strings" "testing" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" - "github.com/context-labs/whip/internal/protocol" ) type setupTestHost struct { setupHost list protocol.ProviderList - flows []daemon.ProviderLoginStatus - writes []daemon.ConfigurationUpdate + flows []protocol.ProviderLoginStatus + writes []protocol.ConfigurationUpdate key string began []string cancelled []string @@ -41,16 +41,16 @@ func (h *setupTestHost) DiscoverProviders(ctx context.Context, model, provider s return h.ListProvidersFor(ctx, model, provider) } -func (h *setupTestHost) ListLogins(context.Context) (daemon.ProviderLoginList, error) { - return daemon.ProviderLoginList{Flows: h.flows}, nil +func (h *setupTestHost) ListLogins(context.Context) (protocol.ProviderLoginList, error) { + return protocol.ProviderLoginList{Flows: h.flows}, nil } -func (h *setupTestHost) UpdateConfiguration(_ context.Context, p daemon.ConfigurationUpdate) (daemon.RuntimeConfiguration, error) { +func (h *setupTestHost) UpdateConfiguration(_ context.Context, p protocol.ConfigurationUpdate) (protocol.RuntimeConfiguration, error) { h.writes = append(h.writes, p) - return daemon.RuntimeConfiguration{}, h.writeErr + return protocol.RuntimeConfiguration{}, h.writeErr } -func (h *setupTestHost) SetProviderKey(_ context.Context, p daemon.ProviderKeySetup) (daemon.RuntimeConfiguration, error) { +func (h *setupTestHost) SetProviderKey(_ context.Context, p protocol.ProviderKeySetup) (protocol.RuntimeConfiguration, error) { h.key = p.Key for i := range h.list.Providers { if h.list.Providers[i].ID == p.Provider { @@ -60,19 +60,19 @@ func (h *setupTestHost) SetProviderKey(_ context.Context, p daemon.ProviderKeySe } } h.list.Revision = "after-key" - return daemon.RuntimeConfiguration{Revision: h.list.Revision}, nil + return protocol.RuntimeConfiguration{Revision: h.list.Revision}, nil } -func (h *setupTestHost) BeginProviderLogin(_ context.Context, provider string) (daemon.ProviderLoginStatus, error) { +func (h *setupTestHost) BeginProviderLogin(_ context.Context, provider string) (protocol.ProviderLoginStatus, error) { h.began = append(h.began, provider) - flow := daemon.ProviderLoginStatus{Provider: provider, FlowID: "flow", State: "pending"} + flow := protocol.ProviderLoginStatus{Provider: provider, FlowID: "flow", State: "pending"} h.flows = append(h.flows, flow) return flow, nil } -func (h *setupTestHost) CancelLogin(_ context.Context, id string) (daemon.ProviderLoginStatus, error) { +func (h *setupTestHost) CancelLogin(_ context.Context, id string) (protocol.ProviderLoginStatus, error) { h.cancelled = append(h.cancelled, id) - return daemon.ProviderLoginStatus{FlowID: id, State: "cancelled"}, nil + return protocol.ProviderLoginStatus{FlowID: id, State: "cancelled"}, nil } func (h *setupTestHost) ProviderCatalogsFor(_ context.Context, provider string, _ bool) (protocol.ProviderCatalogsResult, error) { @@ -275,7 +275,7 @@ func TestSetupEscClosesDialogWithoutCreatingOrConfiguringSession(t *testing.T) { } func TestSetupReusesActiveLoginAndCancelsOnlyThatFlow(t *testing.T) { - h := &setupTestHost{list: setupFixture(), flows: []daemon.ProviderLoginStatus{{Provider: "openai-codex", FlowID: "existing", State: "pending"}}} + h := &setupTestHost{list: setupFixture(), flows: []protocol.ProviderLoginStatus{{Provider: "openai-codex", FlowID: "existing", State: "pending"}}} s := newTestSetup(t, h, true) applySetupCommand(t, s, s.Init()) applySetupCommand(t, s, s.connect(s.list.Providers[2])) @@ -292,7 +292,7 @@ func TestSetupStaleRepliesCannotRestoreClosedOrReplacedFlow(t *testing.T) { s := newTestSetup(t, &setupTestHost{list: setupFixture()}, true) s.request = 2 s.mode = "providers" - s.Update(setupReply{owner: s, request: 1, kind: "login", login: daemon.ProviderLoginStatus{State: "pending", FlowID: "old"}}) + s.Update(setupReply{owner: s, request: 1, kind: "login", login: protocol.ProviderLoginStatus{State: "pending", FlowID: "old"}}) if s.mode != "providers" || s.login.FlowID != "" { t.Fatal("stale reply restored old flow") } @@ -449,7 +449,7 @@ func TestSetupDelayedPollCannotReplaceNewLogin(t *testing.T) { s := newTestSetup(t, h, true) s.list = h.list s.request = 1 - s.login = daemon.ProviderLoginStatus{FlowID: "old", State: "pending"} + s.login = protocol.ProviderLoginStatus{FlowID: "old", State: "pending"} s.mode = "login" late := setupPoll{owner: s, request: s.request, flowID: s.login.FlowID} applySetupCommand(t, s, s.keypress(setupKey("esc"))) @@ -522,8 +522,8 @@ func TestSetupChoiceListsKeepSelectionVisibleOnSmallTerminals(t *testing.T) { name := fmt.Sprintf("Option %02d", i) s.list.Providers = append(s.list.Providers, protocol.ProviderEntry{ID: name, Name: name}) s.catalogs.Models[name] = protocol.ModelDescriptor{Providers: []string{"test"}} - s.login.Teams = append(s.login.Teams, daemon.ProviderChoice{ID: name, Name: name}) - s.login.Projects = append(s.login.Projects, daemon.ProviderChoice{ID: name, Name: name}) + s.login.Teams = append(s.login.Teams, protocol.ProviderChoice{ID: name, Name: name}) + s.login.Projects = append(s.login.Projects, protocol.ProviderChoice{ID: name, Name: name}) } s.selected = 39 rows := s.rows(m) diff --git a/internal/tui/startup_test.go b/internal/tui/startup_test.go index 21305026e..6ca6a6483 100644 --- a/internal/tui/startup_test.go +++ b/internal/tui/startup_test.go @@ -7,11 +7,11 @@ import ( "strings" "testing" - tea "charm.land/bubbletea/v2" - "github.com/charmbracelet/x/ansi" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/protocol" "github.com/context-labs/whip/internal/session" + + tea "charm.land/bubbletea/v2" + "github.com/charmbracelet/x/ansi" ) type onboardingConnection struct { @@ -27,8 +27,8 @@ func (c *onboardingConnection) Call(ctx context.Context, method string, params, *result.(*protocol.ProviderList) = list return err case "provider.key.set": - value, err := c.host.SetProviderKey(ctx, params.(daemon.ProviderKeySetup)) - *result.(*daemon.RuntimeConfiguration) = value + value, err := c.host.SetProviderKey(ctx, params.(protocol.ProviderKeySetup)) + *result.(*protocol.RuntimeConfiguration) = value return err case "query": query := params.(protocol.QueryParams) @@ -47,8 +47,8 @@ func (c *onboardingConnection) Call(ctx context.Context, method string, params, *result.(*protocol.QueryResult) = protocol.QueryResult{Result: raw} return err case "config.update": - value, err := c.host.UpdateConfiguration(ctx, params.(daemon.ConfigurationUpdate)) - *result.(*daemon.RuntimeConfiguration) = value + value, err := c.host.UpdateConfiguration(ctx, params.(protocol.ConfigurationUpdate)) + *result.(*protocol.RuntimeConfiguration) = value return err default: return errors.New("unexpected onboarding request: " + method) @@ -60,11 +60,11 @@ func TestOnboardingStaysInNormalTUIUntilExplicitFirstSend(t *testing.T) { connections := make(chan *onboardingConnection, 4) client, err := NewClient(ClientOptions{ ClientID: "onboarding", DeferCreate: true, - Create: &daemon.CreateSession{Kind: session.SessionKindAgent, CWD: t.TempDir()}, + Create: &session.CreateSession{Kind: session.SessionKindAgent, CWD: t.TempDir()}, Connector: func(context.Context, map[string]int64) (daemonConnection, error) { c := &onboardingConnection{fakeDaemonConnection: newFakeDaemonConnection(session.RootSnapshot{RootID: "first-root"}), host: h} - c.commandFunc = func(p daemon.CommandParams) (daemon.CommandResult, error) { - return daemon.CommandResult{Status: "succeeded", Output: "first-root"}, nil + c.commandFunc = func(p protocol.CommandParams) (protocol.CommandResult, error) { + return protocol.CommandResult{Status: "succeeded", Output: "first-root"}, nil } connections <- c return c, nil @@ -149,7 +149,7 @@ func TestOnboardingStaysInNormalTUIUntilExplicitFirstSend(t *testing.T) { for i, command := range connection.commands { operations[i] = command.Operation } - var selected daemon.CreateSession + var selected session.CreateSession var selectedEffort protocol.EffortParams if len(connection.commands) == 3 { _ = json.Unmarshal(connection.commands[0].Payload, &selected) diff --git a/internal/tui/thin_update.go b/internal/tui/thin_update.go index 5e70d8678..b8d8683bc 100644 --- a/internal/tui/thin_update.go +++ b/internal/tui/thin_update.go @@ -9,10 +9,10 @@ import ( "unicode" "charm.land/bubbles/v2/spinner" - tea "charm.land/bubbletea/v2" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" ) @@ -151,7 +151,7 @@ func (m *model) update(message tea.Msg) (tea.Model, tea.Cmd) { return m, nil } if succeeded && msg.action.Operation == "session.preview" { - var preview daemon.SessionPreviewResult + var preview protocol.SessionPreviewResult if err := json.Unmarshal([]byte(msg.result.Output), &preview); err != nil { m.append(errStyle.Render("session preview: " + err.Error())) } else if m.picker != nil { @@ -177,7 +177,7 @@ func (m *model) update(message tea.Msg) (tea.Model, tea.Cmd) { return m, nil } if succeeded && msg.action.Operation == "provider.catalogs" { - var result daemon.ProviderCatalogsResult + var result protocol.ProviderCatalogsResult if err := json.Unmarshal([]byte(msg.result.Output), &result); err != nil { m.append(errStyle.Render("model catalogs: " + err.Error())) } else { @@ -213,7 +213,7 @@ func (m *model) update(message tea.Msg) (tea.Model, tea.Cmd) { m.verboseCatalogs = false } if succeeded && msg.action.Operation == "agent.submit" { - var result daemon.AgentSubmitResult + var result protocol.AgentSubmitResult if err := json.Unmarshal([]byte(msg.result.Output), &result); err != nil { m.append(errStyle.Render("agent submit: " + err.Error())) } else { @@ -225,7 +225,7 @@ func (m *model) update(message tea.Msg) (tea.Model, tea.Cmd) { } } if succeeded && msg.action.Operation == "agent.transcript" { - var transcript daemon.AgentTranscriptResult + var transcript protocol.AgentTranscriptResult if err := json.Unmarshal([]byte(msg.result.Output), &transcript); err != nil { m.append(errStyle.Render("agent transcript: " + err.Error())) } else if transcript.Agent.ParentID == "" { diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 2a8837b3e..951e05afe 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -14,11 +14,11 @@ import ( "charm.land/bubbles/v2/key" "charm.land/bubbles/v2/spinner" "charm.land/bubbles/v2/textarea" + "github.com/context-labs/whip/internal/protocol" + tea "charm.land/bubbletea/v2" "charm.land/lipgloss/v2" - "github.com/context-labs/whip/internal/config" - "github.com/context-labs/whip/internal/daemon" "github.com/context-labs/whip/internal/llm" "github.com/context-labs/whip/internal/session" "github.com/context-labs/whip/internal/tui/ui" @@ -98,7 +98,7 @@ type menu struct { type model struct { hostCompletion *clientCompletion cfg *config.Config - mcpInventory []daemon.MCPStatusResult // the daemon's last mcp.status rows; the MCP palette builds server rows from these, never from local config + mcpInventory []protocol.MCPStatusResult // the daemon's last mcp.status rows; the MCP palette builds server rows from these, never from local config client *Client clientView clientPresentation clientState ClientState @@ -148,7 +148,7 @@ type model struct { // per streamed request via usageMsg); the status line shows it after the // session spend as "last in(cached)/out tok". lastResp llm.Usage - plan []daemon.PlanItem + plan []protocol.PlanItem showThinking bool // ctrl+o: render reasoning tokens curThink string // in-flight partial reasoning line From d36711aeaf48257025107dd4552f777854010f50 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:41:00 -0700 Subject: [PATCH 49/67] docs: record native client extraction acceptance --- docs/backend-reorganization-plan.md | 56 +++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index ff27b32b7..bc2e38f0e 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -651,7 +651,7 @@ prerequisite. The execution ledger below records subsequent repairs and results. All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. -The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 312 → 313 → performance-probe repair. +The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 312 → 313 → 314 → 315 → 316 → native client extraction. The separate UI-readiness repair now precedes the compatibility gate so that PR #302 inherits that repair in its own required CI. The combined tree at the new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and @@ -681,8 +681,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Gateway fixture synchronization | `067fe82cd90b99aed42efa80c24e3917ba96e820`, [PR #313](https://github.com/context-labs/whip/pull/313), following workspace ownership. | Eight test-only lines synchronize the two pipelined browser writes before backend rejection. Existing assertions remain exact; the detailed baseline diagnosis and checks are below. | | Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | | Shared native plumbing (plan PR 7) | `3127d8ef67c3d59cd70f55ad697102e275c2a6fc`, [PR #315](https://github.com/context-labs/whip/pull/315), based on PR #314. | Shared connection primitives and command presentation move without changing client/server policy. The declaration, characterization, full affected-suite and fresh fixed/immediate-base evidence is recorded below. The PR remains unmerged. | -| Tagged TUI title fixture repair | `codex/backend-reorg-07a-tui-title-fixture`, based on PR #315 (`3127d8ef67c3d59cd70f55ad697102e275c2a6fc`). | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | -| Native client extraction (plan PR 8) | `codex/backend-reorg-08-native-client`, initially based on PR #315. | Exact implementation/private-test moves and canonical Go import changes pass API/source conservation, full ordinary affected race/PTY suites, named native acceptance, static checks and frozen/immediate-parent compatibility. The separate tagged TUI title fixture fails identically on the unchanged parent and candidate; a separate prerequisite repair is required before publication. | +| Tagged TUI title fixture repair | `e289b4ea3344b6fdd45a8782d17c5c66084e90e4`, [PR #316](https://github.com/context-labs/whip/pull/316), based on PR #315. | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | +| Native client extraction (plan PR 8) | `codex/backend-reorg-08-native-client`, based on PR #316 (`e289b4ea3344b6fdd45a8782d17c5c66084e90e4`). | Exact implementation/private-test moves and canonical Go imports preserve all client APIs, bodies and assertions. Full affected race/PTY suites, named native acceptance and static checks passed. After the separate inherited title-fixture repair, the tagged TUI gate and refreshed fixed/immediate-parent guard passed at clean code commit `ecf96616acf48233658620c81286a08fd9bada80`; final documentation records the complete evidence below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1350,7 +1350,7 @@ on clean PR 7 in a real PTY. Its fake implements GenerateTitle(context.Context), but the existing runtime uses GenerateTitle(context.Context, string); its 19-character prompt also falls below the existing 20-rune generation threshold. The provisional title event precedes generated-title completion. These inherited -fixture issues require a separate test-only prerequisite, without changing title +fixture issues required a separate test-only prerequisite, without changing title policy, increasing timeouts or weakening the final title assertion. The original and parent failures are retained in `/private/tmp/whip-pr8-native-acceptance.log` and `/private/tmp/whip-pr8-parent-native-title.log`; PR 8 does not repair them. @@ -1364,6 +1364,48 @@ root/child/content/schema/trace rollback. Toolchains were Go 1.27.0 darwin/arm64 and Node 24.14.1; fixed SDK/backend stays `271c0f8d2a35648d1b45056d57432590b783483c`. Candidate test binary SHA-256 was `8cfe4b022e942473a7f7a1b45c7f2b687a271346586375ed5ce80785f3d4ae6e`. -Publication remains on hold for the separate fixture repair, followed by a -rebase, refreshed immediate-parent proof and compatibility evidence. This entry -does not claim that the inherited tagged gate passed. +Publication was held at that checkpoint for the separate fixture repair. The +initial failure and initial-parent evidence above remain historical results; +the repaired-parent validation below supersedes that publication hold. + + +After independent review of the separate test-only prerequisite [PR #316](https://github.com/context-labs/whip/pull/316), +the extraction was rebased onto its exact head +`e289b4ea3344b6fdd45a8782d17c5c66084e90e4`. Clean code commit +`ecf96616acf48233658620c81286a08fd9bada80` retains both additive CI commands and +all repaired fixture assertions. The rebase changes only that inherited fixture, +CI and the ordered ledger relative to local checkpoint +`c87ecb8e6021480e0a1c83d874d39a982c23fe90`. All 435 production Go files, plus 11 +tracked skill examples, are byte-identical; the prior full affected race results +remain applicable without repeating unchanged suites. Exact tree evidence is +`/private/tmp/whip-pr8-rebase-production-proof.json`. + +Fresh typed reference analysis and expected-source regeneration use the repaired +parent, rather than the earlier snapshot. All 124 API entries still match; +source conservation still covers 1,305 declarations across 109 files, including +1,012 function bodies and 344 named tests. All 534 authored daemon test names +remain exactly once across daemon/client, with precisely the approved 24 moved +tests and one additional architecture test. All 1,257 original Go comments are +preserved verbatim; splitting the autostart test intentionally copies its existing +Unix build constraint into both files. Both extra-declaration/file negative +controls still fail, and all three RPC error frames match the repaired parent's +server constructors byte-for-byte. Refreshed artifacts use the +`/private/tmp/whip-pr8-rebased-` prefix, with the test-name proof at +`whip-pr8-rebased-test-conservation.log`. + +On the rebased code, repaired tagged TUI startup/title acceptance passed both +transports in a real PTY (7.226s). Module build, vet, whipvet, integration-tag +fixture compilation and pinned golangci-lint passed with zero lint issues. All +36 workflow policy tests passed (52.097s), retaining the title fixture command +alongside the client package's existing runtime command. + +The final fresh compatibility run passed at +`/private/tmp/whip-pr8-rebased-compat-fresh/evidence.json`, recording clean candidate +`ecf96616acf48233658620c81286a08fd9bada80`, exact immediate parent +`e289b4ea3344b6fdd45a8782d17c5c66084e90e4`, and an empty candidate diff. Both +transport comparisons, response/order mutation rejection, lifecycle checks and +both-engine fixed/immediate-parent persisted root/child/content/schema/trace +rollback passed. The fixed SDK/backend pin, toolchains and candidate daemon test +binary hash are unchanged from the initial evidence above. The final follow-up +commit changes only documentation; hosted checks will record its own SHA and PR +base. The extraction and its prerequisite remain separate, unmerged review PRs. From 882d1377800830c2723161d2b6f0a5e7db68ee6f Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:46:37 -0700 Subject: [PATCH 50/67] refactor(session): group store lifecycle declarations --- docs/architecture.md | 2 +- docs/backend-reorganization-plan.md | 60 +++++++++++++++++++++++- internal/session/session.go | 65 ------------------------- internal/session/store.go | 73 +++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 67 deletions(-) create mode 100644 internal/session/store.go diff --git a/docs/architecture.md b/docs/architecture.md index b7c123cf1..b772666ee 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -145,7 +145,7 @@ budgets, and private transcript. | `internal/daemonconn` | shared runtime paths, validated local dialing, native launch primitives, initialization limits and event envelope; daemon retains ownership locks and lifecycle policy | | `internal/commandpresentation` | shared formatting of stored command results for existing native text presenters | | `internal/provider` | host provider configuration, discovery, catalogs and account login lifetimes; borrows existing config/auth storage and exposes operations to daemon without importing it | -| `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery and the native session creation value | +| `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery and the native session creation value; connection setup and store lifecycle are grouped in [store.go](../internal/session/store.go) | | `internal/agentdef` | agent definitions and their registry: instructions and discovery toggles, selected modules and capabilities, model and compaction defaults, named children, and the capability-to-operation mapping; `Coding()` and `JuniorDeveloper()` are the first-party definitions | | `internal/rlm` | kernel process, Starlark modules, runtime guide fragments, focused-context composer | | `internal/capability` | identities, grants, path policy, operation admission | diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index bc2e38f0e..2c0c669fc 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -682,7 +682,8 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | | Shared native plumbing (plan PR 7) | `3127d8ef67c3d59cd70f55ad697102e275c2a6fc`, [PR #315](https://github.com/context-labs/whip/pull/315), based on PR #314. | Shared connection primitives and command presentation move without changing client/server policy. The declaration, characterization, full affected-suite and fresh fixed/immediate-base evidence is recorded below. The PR remains unmerged. | | Tagged TUI title fixture repair | `e289b4ea3344b6fdd45a8782d17c5c66084e90e4`, [PR #316](https://github.com/context-labs/whip/pull/316), based on PR #315. | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | -| Native client extraction (plan PR 8) | `codex/backend-reorg-08-native-client`, based on PR #316 (`e289b4ea3344b6fdd45a8782d17c5c66084e90e4`). | Exact implementation/private-test moves and canonical Go imports preserve all client APIs, bodies and assertions. Full affected race/PTY suites, named native acceptance and static checks passed. After the separate inherited title-fixture repair, the tagged TUI gate and refreshed fixed/immediate-parent guard passed at clean code commit `ecf96616acf48233658620c81286a08fd9bada80`; final documentation records the complete evidence below. | +| Native client extraction (plan PR 8) | `d36711aeaf48257025107dd4552f777854010f50`, [PR #317](https://github.com/context-labs/whip/pull/317), based on PR #316. | Exact implementation/private-test moves and canonical Go imports preserve all client APIs, bodies and assertions. Full affected race/PTY suites, named native acceptance and static checks passed. After the separate inherited title-fixture repair, the tagged TUI gate and refreshed fixed/immediate-parent guard passed at clean code commit `ecf96616acf48233658620c81286a08fd9bada80`; final documentation records the complete evidence below. | +| Store lifecycle grouping (plan PR 9) | `codex/backend-reorg-09-store-lifecycle`, based on PR #317 (`d36711aeaf48257025107dd4552f777854010f50`). | Five unchanged declarations and their comments move into `internal/session/store.go`; all 58 remaining declarations are preserved. Connection setup, borrowed references, the daemon guard and database closure now have one small source home. Detailed conservation and validation evidence is recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1409,3 +1410,60 @@ rollback passed. The fixed SDK/backend pin, toolchains and candidate daemon test binary hash are unchanged from the initial evidence above. The final follow-up commit changes only documentation; hosted checks will record its own SHA and PR base. The extraction and its prerequisite remain separate, unmerged review PRs. + +### Store lifecycle grouping and structural stopping point + +The final structural step moves exactly `Store`, `AcquireDaemon`, +`ReleaseDaemon`, `Open` and `Close`, with attached comments, from +`internal/session/session.go` to `internal/session/store.go`. This puts connection +setup, its failure cleanup, borrowed resource references, the in-process daemon +guard and database closure together in one 73-line file. The package, API and +callers are unchanged. `SessionKind`, `Meta`, timestamp helpers and domain +operations remain in session.go; workspace access, permission checks, migrations +and every existing transaction stay in their previous files. + +The external AST-directed extraction proves all five moved declarations and all +58 retained declarations/comments byte-identical. The package documentation stays +in session.go. The package's import dependency set is unchanged; the production +SQLite blank import appears exactly once, now in store.go. No package variable +or init function moves, so neither dependency initialization nor package state +ordering changes. Conserving the production import explicitly matters because +an existing migration test also imports SQLite and could otherwise mask missing +registration. The proof is `/private/tmp/whip-pr9-conservation.log`; the temporary +extraction tool is `/private/tmp/whip-pr9-store-move.go`. Architecture scans are +directory-wide and acceptance selectors use packages/test names, so no guard or +test selector needs alteration. No new test duplicates the exact file move. + +This is the selected persistence follow-up and the final structural change. +Actor and tracing extraction is deferred: their state is still governed by +existing scheduling, mutexes, causal contexts and commit boundaries, without an +equally clear low-risk seam. Root/child scheduling adapters and engine-specific +REPL containment/checkpoint behavior remain as implemented. Final documentation +and integrated review-tip acceptance follow; all review PRs remain unmerged. + +The existing full session race/shuffle suite passed (156.994s). Module build, +vet, whipvet, all-package integration-tag compilation, existing architecture +checks (2.659s) and pinned CI-equivalent golangci-lint 2.13.1 passed with zero +lint issues. Logs are `/private/tmp/whip-pr9-session-race.log` and +`/private/tmp/whip-pr9-build-vet.log`. No unrelated full race suites were repeated +for the byte-identical same-package move. + +Fresh fixed-SDK and exact immediate-parent compatibility passed at +`/private/tmp/whip-pr9-compat-fresh/evidence.json`. The fixed reference remains +`271c0f8d2a35648d1b45056d57432590b783483c`; the immediate parent is PR #317 +`d36711aeaf48257025107dd4552f777854010f50`. All three Go integration binaries, +the fixed SDK and generated artifacts were rebuilt using Go 1.27.0 darwin/arm64 +and Node 24.14.1. Both transports' calibrated responses/errors/ordered events, +actual response/order mutation rejection, lifecycle scenarios and both-engine +fixed-base/immediate-base → candidate → base retained-root/child/content/schema/ +trace rollback passed. Candidate binary SHA-256: +`02666aa9f94a6623d24bbb33407a937274975b2977a1cbaa39e94f5f4713f5af`. + +This local run records the PR #317 HEAD plus the complete staged candidate diff, +including the newly added store.go. Only this ledger was updated after that +capture; all candidate Go source remains identical to the tested source. A +separate dependency setup had completed before the guard began its candidate +installation; recorded timestamps confirm no concurrent installation or build +in that directory (`/private/tmp/whip-pr9-installer-timing.json`). Hosted checks +will record the submitted commit and actual PR base separately. This PR remains +unmerged pending human review. diff --git a/internal/session/session.go b/internal/session/session.go index 350c2c8cd..21b1fcf96 100644 --- a/internal/session/session.go +++ b/internal/session/session.go @@ -8,15 +8,9 @@ import ( "errors" "fmt" "io" - "path/filepath" "strings" - "sync/atomic" "time" - _ "modernc.org/sqlite" - - "github.com/context-labs/whip/internal/capability" - contentstore "github.com/context-labs/whip/internal/content" "github.com/context-labs/whip/internal/llm" ) @@ -59,63 +53,6 @@ type Meta struct { UpdatedAt time.Time `json:"updated_at"` } -type Store struct { - db *sql.DB - content *contentstore.Store - workspaces *capability.Workspaces - daemonOwned atomic.Bool - globalRules atomic.Pointer[[]string] // config permissions.allow, "operation:rule" entries -} - -// AcquireDaemon is the in-process guard for one Daemon per Store. The runtime -// also holds the cross-process socket/file lock before constructing the Store. -func (s *Store) AcquireDaemon() bool { return s.daemonOwned.CompareAndSwap(false, true) } -func (s *Store) ReleaseDaemon() { s.daemonOwned.Store(false) } - -// Open opens (creating if needed) the sessions database at path and borrows workspaces. -func Open(path string, workspaces *capability.Workspaces) (*Store, error) { - if workspaces == nil { - return nil, errors.New("session store requires a workspace coordinator") - } - db, err := sql.Open("sqlite", path) - if err != nil { - return nil, err - } - db.SetMaxOpenConns(1) - failed := true - defer func() { - if failed { - _ = db.Close() - } - }() - if _, err := db.ExecContext(context.Background(), "PRAGMA busy_timeout=5000"); err != nil { - return nil, err - } - if err := migrate(context.Background(), db, path); err != nil { - return nil, err - } - for _, pragma := range []string{ - "PRAGMA journal_mode=WAL", // faster commits, no read/write blocking - "PRAGMA synchronous=NORMAL", // safe in WAL; skips per-commit fsync - "PRAGMA temp_store=MEMORY", - "PRAGMA foreign_keys=ON", - } { - if _, err := db.ExecContext(context.Background(), pragma); err != nil { - return nil, err - } - } - content, err := contentstore.New(filepath.Dir(path)) - if err != nil { - return nil, err - } - store := &Store{ - db: db, content: content, - workspaces: workspaces, - } - failed = false - return store, nil -} - // SetGoal stores the session's active goal ("" clears it). func (s *Store) SetGoal(id, goal string) error { _, err := s.db.ExecContext(context.Background(), `UPDATE sessions SET goal=? WHERE id=?`, goal, id) @@ -170,8 +107,6 @@ func (s *Store) SetUsage(id string, in, cached, out int) error { return err } -func (s *Store) Close() error { return s.db.Close() } - // stampLayout is RFC 3339 with a fixed nine-digit fraction: stored stamps // keep nanoseconds, sort lexicographically as text, and still parse with // time.RFC3339. Every stamp that is stored or compared in SQL goes through diff --git a/internal/session/store.go b/internal/session/store.go new file mode 100644 index 000000000..51edec2da --- /dev/null +++ b/internal/session/store.go @@ -0,0 +1,73 @@ +package session + +import ( + "context" + "database/sql" + "errors" + "path/filepath" + "sync/atomic" + + _ "modernc.org/sqlite" + + "github.com/context-labs/whip/internal/capability" + contentstore "github.com/context-labs/whip/internal/content" +) + +type Store struct { + db *sql.DB + content *contentstore.Store + workspaces *capability.Workspaces + daemonOwned atomic.Bool + globalRules atomic.Pointer[[]string] // config permissions.allow, "operation:rule" entries +} + +// AcquireDaemon is the in-process guard for one Daemon per Store. The runtime +// also holds the cross-process socket/file lock before constructing the Store. +func (s *Store) AcquireDaemon() bool { return s.daemonOwned.CompareAndSwap(false, true) } +func (s *Store) ReleaseDaemon() { s.daemonOwned.Store(false) } + +// Open opens (creating if needed) the sessions database at path and borrows workspaces. +func Open(path string, workspaces *capability.Workspaces) (*Store, error) { + if workspaces == nil { + return nil, errors.New("session store requires a workspace coordinator") + } + db, err := sql.Open("sqlite", path) + if err != nil { + return nil, err + } + db.SetMaxOpenConns(1) + failed := true + defer func() { + if failed { + _ = db.Close() + } + }() + if _, err := db.ExecContext(context.Background(), "PRAGMA busy_timeout=5000"); err != nil { + return nil, err + } + if err := migrate(context.Background(), db, path); err != nil { + return nil, err + } + for _, pragma := range []string{ + "PRAGMA journal_mode=WAL", // faster commits, no read/write blocking + "PRAGMA synchronous=NORMAL", // safe in WAL; skips per-commit fsync + "PRAGMA temp_store=MEMORY", + "PRAGMA foreign_keys=ON", + } { + if _, err := db.ExecContext(context.Background(), pragma); err != nil { + return nil, err + } + } + content, err := contentstore.New(filepath.Dir(path)) + if err != nil { + return nil, err + } + store := &Store{ + db: db, content: content, + workspaces: workspaces, + } + failed = false + return store, nil +} + +func (s *Store) Close() error { return s.db.Close() } From 529026159836fee4f74bd3cd117c937f64dee147 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 02:57:28 -0700 Subject: [PATCH 51/67] docs: close out frozen-contract backend reorganization --- docs/architecture.md | 151 +++++++++++----- docs/backend-redesign-plan.md | 6 +- docs/backend-reorganization-plan.md | 257 ++++++++++++++++++++-------- 3 files changed, 303 insertions(+), 111 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index b772666ee..5438bbf7a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -11,10 +11,11 @@ those views. It never starts a daemon, runs an agent loop, owns provider keys, o creates another history database. See [SDK usage](../packages/sdk/README.md) for identity, cancellation, recovery, content and application ownership contracts. -whip is organized around one recursive agent abstraction. A root and a child -are both `AgentSession`s: each owns a provider loop, a bounded Starlark kernel, -a durable transcript, and an identity. Every model sees exactly one tool, -`rlm_exec`. +Model-driven roots and children both use `AgentSession` for the provider/tool +loop. Each has its own identity and transcript; descendants inherit the root +session's execution engine. Starlark and QuickJS (JavaScript) run behind the +same model-facing tool, `rlm_exec`, with engine-specific containment and +checkpoint formats. Tool-host roots expose services without a provider loop. ```mermaid flowchart TB @@ -26,7 +27,8 @@ flowchart TB WEB["React web application + TypeScript SDK"] end - RPC["trusted WHIP v4 daemon protocol"] + GATEWAY["separate web gateway process"] + RPC["trusted WHIP 6.9 daemon protocol"] subgraph daemon["whip _daemon"] ROOT["root actor"] @@ -40,7 +42,10 @@ flowchart TB KERNELS["disposable whip _kernel workers"] MODELS["model providers"] - TUI & RUN & ACP & BRIDGE & WEB <--> RPC <--> ROOT + TUI & RUN & ACP & BRIDGE <--> RPC + WEB <-->|HTTP / WebSocket| GATEWAY + GATEWAY <-->|Unix socket| RPC + RPC <--> ROOT ROOT <--> STORE ROOT --> TREE TREE <--> MODELS @@ -54,16 +59,17 @@ flowchart TB ## Core invariants 1. **One model-facing interface.** Neither root nor child receives direct JSON - file, shell, MCP, or child tools. Those capabilities are Starlark modules - behind `rlm_exec`. + file, shell, MCP, or child tools. Those capabilities are host modules + behind `rlm_exec` in the selected execution engine. 2. **One recursive session type.** Children are not one-shot tasks. They are retained sessions that can take later turns and create their own children within the configured depth and budget limits. 3. **One authority path.** Built-in effects enter the capability dispatcher; state, messages, schedules, and lifecycle changes enter root-actor APIs. -4. **Admission precedes durable execution.** Client commands are journaled - before a turn. Child kernel capacity is reserved before the child record is - committed, so a rejected spawn cannot leave a ghost agent. +4. **Durable admission precedes execution.** Client commands are journaled + before a turn. Child admission durably records the child, initial prompt and + delegated authority/budgets before publishing and waking it. Admitted children + queue for the shared worker pool; admission does not reserve an idle worker. 5. **Communication is explicit.** An agent response is local to that agent. Parent and child exchange durable messages; notifications contain metadata, never message bodies. @@ -91,7 +97,7 @@ sequenceDiagram RootActor->>Store: admit command + inbox sequence RootActor->>Agent: start turn with focused context Agent->>Model: prompt + rlm_exec definition - Model->>Kernel: rlm_exec(Starlark) + Model->>Kernel: rlm_exec(program) Kernel->>Host: typed module calls Host->>Store: authorize / reserve / commit Kernel-->>Model: bounded result or handle @@ -100,20 +106,23 @@ sequenceDiagram RootActor-->>Client: ordered events + stored result ``` -Child turns use the same `AgentSession` model and tool path. Today the root -actor and child wake path still use different scheduling/commit adapters; the -single-runtime consolidation plan removes that final lifecycle split. The -intended differences are only parent ID, delegated capabilities, effective -budgets, and private transcript. +Child turns use the same `AgentSession` model and tool path. The root actor and +child wake path retain distinct scheduling and commit adapters. Sharing a model +loop does not make those lifecycles identical. See [concurrency](concurrency.md) +for admission and worker ownership, and [execution language and checkpoints](rlm-runtime.md#execution-language-and-checkpoints) +for the engine-specific guarantees. The backend reorganization changes neither. ## Process and storage boundaries - `whip _daemon` is the sole owner of the runtime database, live agents, integrations, permissions, and managed processes. -- `whip _kernel` evaluates Starlark with bounded steps, host calls, memory, - wall time, output, and frames. It has no ambient provider credentials or - direct filesystem/network API. -- Clients use one typed WHIP v4 contract in JSON-RPC 2.0 envelopes over Unix +- The separate web gateway serves packaged assets and browser HTTP/WebSocket + traffic, forwarding runtime operations over the daemon's Unix socket. +- `whip _kernel` evaluates the selected Starlark or QuickJS engine with its + existing limits on execution, host calls, memory, output and frames. It has no + ambient provider credentials or direct filesystem/network API. Checkpoint + fidelity and containment remain engine-specific. +- Clients use one typed WHIP 6.9 contract in JSON-RPC 2.0 envelopes over Unix newline framing or WebSocket text messages. Transport adapters share validation and application handlers. No v1 codec or build-equality attachment check remains. - Commands acknowledge committed acceptance; the daemon supervises execution. @@ -126,14 +135,18 @@ budgets, and private transcript. - Every connected client is trusted to answer permission requests and change permission modes. There is no pairing, signing key or client authentication. Agent capabilities, budgets, content grants and delegated MCP authority remain - daemon-enforced; browser Host/Origin validation remains transport-owned. + daemon-enforced; browser Host/Origin validation remains gateway-owned. - Provider onboarding, credentials, workspace completion and shared configuration are execution-host services. Only presentation preferences remain client-owned. -- SQLite WAL with synchronous=NORMAL retains daemon-crash durability. The fresh - schema rejects incompatible databases without deletion or migration. +- SQLite WAL with synchronous=NORMAL retains daemon-crash durability. The current + schema is **21**, identity `whip-recursive-runtime-v21`. Existing migrations + upgrade recognized matching schemas 10 through 20; older, newer or unrecognized + stores are rejected without deletion. These rules are unchanged. - Runtime data lives under `~/.whipcode/runtime-v2/` (or - `$WHIPCODE_HOME/runtime-v2/`). Pre-reset installations require the explicit - [manual reset](team-reset.md); old stores are not imported. + `$WHIPCODE_HOME/runtime-v2/`). The historical [manual reset](team-reset.md) + applies to unsupported pre-reset installations, not supported migration paths. + This reorganization's binary rollback checks compare schema-21 builds; they + do not promise downgrade across earlier one-way migrations. ## Package map @@ -147,7 +160,7 @@ budgets, and private transcript. | `internal/provider` | host provider configuration, discovery, catalogs and account login lifetimes; borrows existing config/auth storage and exposes operations to daemon without importing it | | `internal/session` | durable commands, transcripts, agents, messages, budgets, recovery and the native session creation value; connection setup and store lifecycle are grouped in [store.go](../internal/session/store.go) | | `internal/agentdef` | agent definitions and their registry: instructions and discovery toggles, selected modules and capabilities, model and compaction defaults, named children, and the capability-to-operation mapping; `Coding()` and `JuniorDeveloper()` are the first-party definitions | -| `internal/rlm` | kernel process, Starlark modules, runtime guide fragments, focused-context composer | +| `internal/rlm` | Starlark and QuickJS kernel engines, host modules, runtime guide fragments, focused-context composer | | `internal/capability` | identities, grants, path policy, operation admission | | `internal/tools` | concrete built-in services reached through host modules | | `internal/mcp` | external MCP connections and named tool calls | @@ -158,15 +171,59 @@ budgets, and private transcript. | `packages/app` | React routes and workflows, SDK view leases, host query presentation, application drafts and preferences; no daemon/process ownership | | `apps/web` | browser entry, storage/clipboard/download/link adapters, Vite build and browser acceptance | | `internal/theme`, `cmd/themegen` | renderer-independent theme resolution and deterministic UI catalog generation | -| `internal/webassets`, `cmd/whip/web.go` | embedded web asset serving/discovery and explicit browser launch against an existing daemon | +| `internal/webgateway` | separate browser gateway, Host/Origin validation and forwarding to the existing daemon | +| `internal/webassets`, `cmd/whip/web.go` | packaged assets and explicit foreground/check/open gateway commands against an existing daemon | + +Startup composes daemon orchestration, provider services and storage. Native Go +clients depend on the existing protocol/framing and neutral connection primitives, +without importing `daemon`; TUI and ACP production code imports the client. +Integration tests retain real daemon fixtures where needed. The protocol package +still imports canonical `session`, `config`, `llm`, `capability` and `mcp` values. +It is not a dependency-free leaf. Those representation dependencies avoid a new +model or translation layer. The native `CreateSession` value lives in `session`, +with identity-preserving aliases in daemon and client; stored-result presentation +has one unchanged decoder in `commandpresentation`. + +Provider configuration retains its existing atomic host-configuration update and +provisioning lock, including fields outside provider setup. Host MCP import/icon +ownership lives in [mcp_import_service.go](../internal/daemon/mcp_import_service.go); +directory handlers are grouped in [host_directory.go](../internal/daemon/host_directory.go). Neither +requires a new protocol or independent copy of configuration. + +## Construction and resource lifetimes + +| Resource | Constructor and borrowers | Owner and cleanup | +| --- | --- | --- | +| Session store | Startup opens it after the cross-process owner lock. Runtime/domain operations borrow it. | The caller owns it if `daemon.New` fails; successful construction transfers ownership to the daemon. `Daemon.Close` closes it after borrowers and the process manager. | +| Shared process manager | Startup constructs one immediately after successful `session.Open`, preserving the environment snapshot point. Roots, children, tools and MCP borrow that exact pointer. | Caller-owned on failed `daemon.New`; daemon-owned on success. Root teardown still uses `StopRoot`. Global close joins manager and database errors in that order and caches the result. A new store lifetime receives a new manager. | +| Workspace coordinator | Startup constructs it immediately before `session.Open`; storage borrows it and keeps the existing `Workspaces()` accessor for authority checks and tool borrowers. | No close operation or fallback allocation. Existing root and delegation authorization order, including transactions, is unchanged. | +| Provider service | Startup constructs it; the server uses it and host MCP borrows its cancellation context. | `Server.Close` closes it before daemon shutdown. Startup's existing deferred close remains. | +| Kernel manager | Startup constructs it; the runtime factory and agent sessions borrow it. | Existing runtime releases and startup's deferred close retain worker lifetime and sharing. | + +The existing factory and its helpers live in +[daemon_runtime.go](../cmd/whip/daemon_runtime.go). Configuration reload and kernel +command construction still run at the same invocation points. Within storage, +[store.go](../internal/session/store.go) groups connection setup, borrowed resource +references, the daemon ownership guard and database closure; domain models, SQL, +authority checks and transactions remain in their existing files. + +These lifetimes are not a generic `CloseAll` sequence. `Server.Close` tears down +browser providers, listeners, connections and uploads before provider/daemon +shutdown; `Daemon.Close` waits for roots and accepted background work before +closing the process manager and database. Failed construction retains the +caller's resources and releases the in-process guard where it acquired it. +Actor scheduling and tracing bookkeeping stay beside their current locks, +causal contexts and commit boundaries. There is no equally clear, low-risk +extraction to justify moving them in this effort. ## Browser application ownership `createWhipApplication(platform)` creates one application runtime, TanStack Query client and router. The platform supplies storage, external links, clipboard and -downloads; a future Electron shell can provide those effects without replacing -the application or SDK. The browser entry initializes appearance before mounting -React, connects explicitly, and disposes local resources on page teardown. +downloads; the Electron shell supplies native effects while consuming the same +web renderer artifact and SDK contracts. The browser entry initializes appearance +before mounting React, connects explicitly, and disposes local resources on page +teardown. The SDK remains authoritative for reconstructing session state from protocol snapshots, history and events. TanStack Query handles bounded host reads and @@ -182,10 +239,12 @@ The shared Go resolver owns terminal ANSI/Chroma semantics, and the UI derives readable browser foregrounds while retaining the exact source catalog. Theme changes preserve route, draft, scroll and highlighted-code identities. -The daemon serves packaged assets and API traffic on its existing optional -listener. `whipcode web` discovers and opens that endpoint; it never starts or -replaces the daemon. Browser clients are trusted to make permission decisions, -while internal capabilities and content grants remain daemon-enforced. See +The separate gateway serves packaged assets and browser API traffic for an +existing daemon. `whipcode web` runs a foreground gateway, checks an existing +one, or opens an explicit URL; it never starts, restarts or reconfigures the +daemon. Opt-in managed startup supervises a gateway child. Browser clients are +trusted to make permission decisions, while internal capabilities and content +grants remain daemon-enforced. See [web-app.md](web-app.md) for launch, development proxy and trusted-network setup. Read [rlm-runtime.md](rlm-runtime.md) for the programming model and @@ -196,14 +255,20 @@ content grants, and opt-in local/trusted-network setup. ### Session tab ownership -The web window owns up to 32 root-tab identities per connected runtime, while only -one conversation is mounted and at most four SDK views are retained. TanStack -Router owns selection and child/inspector search state; window sessionStorage owns -only bounded layout metadata. The bounded `sessions.summaries` query -supplies advisory descendant activity and human-input counts without opening roots. -Uploads and reading bookmarks belong to AppRuntime so navigation can release a -view without losing unsent work or the reader's place. Closing a tab has no daemon -execution meaning. See [web-app.md](web-app.md#session-tabs) for limits and behavior. +The window owns one workspace across hosts, with up to 32 open views in four +panes. Each visible pane mounts its selected conversation; duplicate views share +SDK observation. The four-root retention budget is window-wide, with unused +views expiring after 30 seconds and actively leased roots never evicted. App +`SessionTabs` owns the split tree and pane selection, while TanStack Router owns +route and child/inspector search state. Browser sessionStorage holds bounded +layout metadata; desktop uses namespaced localStorage. The bounded +`sessions.summaries` query supplies advisory activity and human-input counts +without opening roots. Uploads and reading bookmarks belong to AppRuntime, so +navigation can release a view without losing unsent work or the reader's place. +Closing a conversation tab has no daemon execution meaning. See +[session tabs and split views](web-app.md#session-tabs-and-split-views) and the +[frontend ownership guide](frontend.md#split-workspace) for current limits and +behavior. Model budget rows distinguish finite limits from explicit unlimited values. diff --git a/docs/backend-redesign-plan.md b/docs/backend-redesign-plan.md index 477abdd20..5e4ee3e1c 100644 --- a/docs/backend-redesign-plan.md +++ b/docs/backend-redesign-plan.md @@ -1,6 +1,10 @@ # Whip backend redesign and delivery plan -Status: proposed; implementation has not started under this plan. +Status: historical proposal; superseded for the current backend cleanup by +[Backend reorganization with a frozen client contract](backend-reorganization-plan.md). +The replacement protocol/schema/client scope below is not active for that work. + +Original status: proposed; implementation had not started under this plan. Written: 2026-09-27. Planning reference: `6f02507bf`. Build a simpler Go backend with explicit ownership, uniform root/child sessions, diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 2c0c669fc..6d925a19d 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -1,6 +1,16 @@ # Backend reorganization with a frozen client contract -Status: implementation authorized; preparing an unmerged PR stack for review. +Status: structural work complete; documentation prepared for human review. +All active PRs remain unmerged. Final local integrated acceptance passed on the +implementation tip below. Hosted closeout checks are pending as of this record; +completed hosted results belong in the closeout PR and final handoff. + +Implementation review tip: [`882d1377800830c2723161d2b6f0a5e7db68ee6f`](https://github.com/context-labs/whip/commit/882d1377800830c2723161d2b6f0a5e7db68ee6f), +[PR #318](https://github.com/context-labs/whip/pull/318). This documentation-only +closeout is based on that tip; it is not merged development. + +Start with [PR navigation and review checkpoints](#8-pr-ci-and-review-policy) or +the [final evidence and limitations](#documentation-closeout-and-integrated-review-tip). Execution instruction, September 29: the user authorized end-to-end overnight execution with all work ready for morning review. For this execution, prepare @@ -81,10 +91,12 @@ These apply to every PR, including an apparently mechanical move. intervening commits. Review those deltas explicitly before updating the baseline; never silently redefine compatibility as whatever now passes. 7. **Work sequentially in reviewed stacks.** One PR under active implementation - or review at a time; human approval before starting the next. Reviewed PRs - remain stacked until the checkpoint for their group, then merge in dependency - order. No parallel stream of speculative follow-up PRs. Each step must work - independently and preserve all existing gates. + or review at a time, with agent source review and local evidence before the + next structural step. The overnight instruction supersedes the originally + agreed human approval between steps. Human review remains pending; every + active PR stays unmerged until authorized checkpoint merges. No parallel + stream of speculative follow-up PRs. Each step must work independently and + preserve all existing gates. 8. **Allow mechanical Go client moves.** Moving the existing Go client into a dedicated package and updating CLI/TUI/ACP imports is in scope. Preserve its APIs and behavior apart from internal Go import paths. The TypeScript SDK @@ -124,19 +136,21 @@ This plan supersedes [backend-redesign-plan.md](backend-redesign-plan.md) **as the proposal for this reorganization**. The earlier plan remains historical context, not an additional set of requirements. Current implementation guides remain authoritative about implemented behavior; a stale reference in a guide -must be checked against code. For example, some architecture prose still calls -the protocol v4, while `internal/protocol/types.go` declares 6.9. +must be checked against code. At research time, architecture prose still called +the protocol v4 although `internal/protocol/types.go` declared 6.9. Closeout +corrects that prose without changing the implementation. -### Current ownership and coupling +### Starting-revision ownership and coupling -The package inventory found 44 Go packages. On the active macOS build, +This is the research snapshot at `271c0f8d2a35648d1b45056d57432590b783483c`, +not an inventory of the completed review tip. The package inventory found 44 Go packages. On the active macOS build, `internal/daemon` has 82 production Go files and 123 test files; `internal/session` has 55 and 67 respectively. These are orientation figures, not targets. Go language-server analysis found 376 references to `Store` across 91 files and 73 to `ProviderService` across 21 files, including tests. Refresh references for the exact revision and build tags before each move. -| Area | Current evidence | Consequence for the plan | +| Area | Starting-revision evidence | Consequence for the plan | | --- | --- | --- | | Daemon | `daemon.go`, `session.go`, `server.go`, provider services, clients, host handlers, recursive runtime, and transport-facing code share a package. | Separate coherent outer responsibilities before touching actor scheduling. | | Provider setup | `ProviderService` owns login flows, credentials/catalog operations, and configuration, but also MCP import methods and lazy brand-icon state. | Separate the unrelated MCP host responsibility before moving provider implementation. | @@ -150,7 +164,7 @@ Refresh references for the exact revision and build tags before each move. | Tracing | `daemon/spans.go` records causal relationships at runtime; `session/span.go` and OTLP code persist/query/export them. | Keep recording at the same execution points. Moving tracing into a delayed observer would change behavior. | | Startup | `cmd/whip/daemon.go` combines locks, configuration, provider discovery, factory construction, kernels, server, gateway, and shutdown. | Small construction helpers and explicit ownership improve readability without a new framework. | -### Baseline is not yet green +### Historical baseline failure and separate prerequisite repairs The [CI run for the starting revision](https://github.com/context-labs/whip/actions/runs/36674593257) failed. The inspected [SDK job](https://github.com/context-labs/whip/actions/runs/36674593257/job/109756705168) @@ -159,13 +173,13 @@ stopped at `npm audit --omit=dev --audit-level=high`, reporting a high-severity did not run. This is not evidence of an SDK behavior regression, and successful Go jobs do not establish a green product baseline. -Resolve baseline failures in separate prerequisite PRs, then run the complete -required gate. Do not lower the audit threshold, drop tests, waive the aggregate -gate, or call skipped checks successful. Any additional failures exposed after -the audit is repaired require the same treatment. This proposal records a -research result, not a completed local acceptance run. +That audit failure and later exposed fixture failures were diagnosed and +repaired in separate prerequisite PRs, recorded in the [execution ledger](#execution-ledger). +The audit threshold, product assertions and aggregate gate were preserved. +This paragraph records the original research finding; later evidence must be +read at its recorded revision and must not count a skipped check as successful. -## 4. Intended boundaries +## 4. Boundaries implemented in the review stack Keep one Go module and ordinary `internal` packages. Use constructors and direct calls. No DI container, service locator, generic repository layer, event bus, @@ -176,17 +190,19 @@ new workflow framework, or package per database table. This fits Go's | --- | --- | --- | | `cmd/whip` startup | Configuration, process locks, construction, handoff of ownership, shutdown wiring. | May compose all backend packages. Keep explicit startup order. Add a separate application package only if a real second caller needs it. | | `internal/daemon` | Server entry points, root registry, root actor, command coordination, existing runtime composition. | Calls provider/host services and storage. It remains the integration point; shrinking it does not require emptying it. | -| Proposed `internal/provider` | Existing provider setup, authentication flows, discovery/catalog selection, host configuration operations used by that service. | Existing config/auth/LLM packages and unchanged protocol types. Must not import `daemon` or own turns. | -| Host MCP component | Import offers, applying host MCP configuration, and current icon lookup used by that surface. | Initially a small component inside `daemon`; separate package only when dependencies justify it. No session MCP lifecycle ownership. | -| Host directory component | Current list/create/pick behavior and OS-specific implementation. | Initially grouped separately inside `daemon`. A later package must preserve existing protocol errors directly, without inventing an error translation model. | +| `internal/provider` | Existing provider setup, authentication flows, discovery/catalog selection, host configuration operations used by that service. | Existing config/auth/LLM packages and unchanged protocol types. Must not import `daemon` or own turns. | +| Host MCP component | Import offers, applying host MCP configuration, and current icon lookup used by that surface. | Private `hostMCPService` in `daemon`, owned by `Server`, borrowing provider cancellation. No session MCP lifecycle ownership. | +| Host directory component | Current list/create/pick behavior and OS-specific implementation. | Grouped in `daemon/host_directory.go`; existing protocol errors and callers remain in the same package. | | `internal/session` | SQLite/content persistence, existing durable models, atomic transitions and queries. | No actor or provider construction. Keep existing transaction logic and representations. It may borrow the existing workspace resolver for authority checks. | -| Daemon resource owner | One shared process manager and workspace lock coordinator, passed to tools/MCP/runtime as today. | Ownership is explicit; scope and lifetime stay unchanged. Resource implementations remain in `capability`. | +| Explicit resource composition | Startup constructs one process manager immediately after store open and transfers it only on successful `daemon.New`; startup constructs workspaces immediately before store open and storage borrows them. | Root/child/tool/MCP pointers, snapshot timing and teardown order are unchanged. Failed daemon construction leaves resources with the caller. Implementations remain in `capability`; workspaces have no close operation. | | Existing `agent`, `rlm`, `tools`, `capability`, `mcp`, `llm` | Existing model loop primitives, kernels, tools, authority enforcement, integration machinery, provider encoders. | Keep their established responsibilities. No broad modernization sweep. | | `internal/client` | Existing Go `Client`/`RootClient` and client service methods. | Existing protocol and framing; no dependency on the server/agent runtime implementation. Mechanical Go caller import changes are allowed; client APIs and behavior remain unchanged. | -| Existing `protocol` and `protocoltransport` | Current public representations, schemas, negotiation, and framing. | Preserve contract and representation ownership. Do not force storage to import protocol and create a cycle. | +| `internal/daemonconn` | Shared paths, local dialing, launch primitives, initialization constants and event envelope. | No daemon ownership locks, restart/admission policy or client implementation. One existing executable-resolution seam remains. | +| `internal/commandpresentation` | Existing stored command-result text decoder shared by native consumers. | One unchanged decoder; client-only fill logic stays in `client`. Canonical native `CreateSession` lives in `session` with type aliases preserving identity. | +| Existing `protocol` and `protocoltransport` | Current public representations, schemas, negotiation, and framing. | Preserve contract and representation ownership. Protocol still imports existing session/config/LLM/capability/MCP values; do not force storage to import protocol and create a cycle. | The desired direction is startup → daemon orchestration → services/storage, -with clients → protocol/framing. This is a responsibility map, not a claim that +with clients → protocol/framing/daemonconn. This is a responsibility map, not a claim that the existing type graph has already become a strict layered architecture. Check actual imports after each step and document remaining justified edges. @@ -282,18 +298,21 @@ than SQLite file bytes. No two binaries may own the same home concurrently. Each numbered item describes a reviewable change with its own evidence. If it needs multiple coherent moves, split it **before implementation**, preserving -the same review-before-next cadence. Aim for roughly 100–500 substantive changed +the sequential agent-review/evidence cadence for this overnight execution. Aim for roughly 100–500 substantive changed lines per PR. A large pure move needs a clear move-aware diff and explicit review scope; it is not permission to include cleanup or behavior changes. ### Prerequisites: repair and establish the baseline -- Handle the current dependency-audit failure and any subsequently exposed +The following requirements were carried out in the separate prerequisite PRs +listed in the ledger; they remain requirements for any newly exposed failure. + +- Handle the starting dependency-audit failure and any subsequently exposed failures as independent maintenance/bug PRs. Avoid broad automated upgrades. - Re-run the full existing CI and acceptance gates. Record a green execution base and its relationship to the starting revision. -- Enable CI for the stacked PR bases before creating dependent PRs. Currently - `ci.yml` triggers PRs only against `main` or `development`. Extend PR +- Enable CI for the stacked PR bases before creating dependent PRs. At the starting revision, + `ci.yml` triggered PRs only against `main` or `development`. Extend PR triggering to this effort's `codex/backend-reorg-*` base branches using the **same full gate**, and verify it runs on a PR targeting a parent branch. Do not broaden release/publish triggers or add a reduced substitute workflow. @@ -450,13 +469,20 @@ acceptance, transport tests, replay/cancellation tests, and package builds pass. Do not retain a forwarding layer in `daemon` as a substitute for migrating the internal Go callers. -### PR 9 and later — Smaller actor and persistence responsibilities, selectively +### PR 9 — Selected persistence grouping; actor and tracing splits deferred + +The selected follow-up is [PR #318](https://github.com/context-labs/whip/pull/318): +move only `Store`, `Open`, `Close`, `AcquireDaemon` and `ReleaseDaemon` unchanged +into `internal/session/store.go`. This groups connection setup and lifetime +without changing the package, callers, domain models, SQL or transactions. -Do not begin with a wholesale split of `Session`, `RecursiveRuntime`, or -`Store`. Choose one concrete responsibility at a time after refreshing the -reference map and identifying a future change it would make easier. +The original candidates below record the selection criteria, not remaining +promised work. Actor and tracing extractions stop here: their behavior crosses +existing scheduling, locks, causal contexts and commit boundaries, and research +did not establish a comparably useful low-risk seam. No wholesale split of +`Session`, `RecursiveRuntime` or `Store` is authorized. -Candidate individual PRs, in increasing risk: +Original candidates, in increasing risk: - Group persistence operations by existing responsibility within `session` without moving durable types or changing SQL/transactions. Do not introduce @@ -488,7 +514,8 @@ ownership map, including intentional remaining coupling. Follow [frontend.md](frontend.md) if a Go client move affects documented client boundaries. Keep a concise PR/evidence ledger in this plan; avoid a second competing architecture guide. Run full final acceptance and the fixed-client -and data rollback scenarios on the integrated development revision. +and data rollback scenarios on the integrated review-tip revision. Development +is verified separately and remains unchanged until authorized merges. ## 7. Lifecycle rules for every extraction @@ -519,31 +546,35 @@ pointed-to resource becomes available or ceases to be usable. ## 8. PR, CI, and review policy -Use `codex/backend-reorg-<step>-<topic>` branches from the accepted development -base. Preserve each useful change as a separate PR and commit history. Review -the first PR before starting its successor. +This execution prepares one sequential review stack on +`codex/backend-reorg-<step>-<topic>` branches. Every successor targets its +immediate parent's branch, including across checkpoint groups. Each structural +step receives agent source review and local compatibility evidence before its +successor begins; hosted results and separate baseline repairs are recorded in +the ledger. Human review remains pending, and no active PR has been merged. -The first PR of each group targets development. Each successor targets its -immediate parent's branch, and work begins only after that parent is approved -and green. Reviewed parents remain open until the group's checkpoint. There is -only one PR under active implementation or review; the other open PRs are -already reviewed dependencies. +The groups below are suggested human review and eventual merge boundaries, not +claims of human approval. Review individual diffs against their immediate parent +and the combined tip against the fixed starting revision. Assess the improvement +at each checkpoint before deciding whether later groups warrant their risk. -| Merge checkpoint | Group | Evidence required before merging the group | +| Review and eventual merge checkpoint | Actual PR navigation, in dependency order | Required evidence | | --- | --- | --- | -| Baseline and guardrails | Separate prerequisite repairs/CI setup, then PR 1 (split into sequential PRs if needed). | Full baseline is green; stacked-base CI and frozen-client checks work. Land prerequisite repairs before establishing their dependent baseline. | -| Provider boundary | PRs 2, 3a, 3b1, and 3b2. | Host MCP and provider responsibilities are separated; configuration atomicity, provider semantics, and unchanged clients are verified. | -| Resource ownership | PRs 4, 5, and 6. | Startup, process ownership, and workspace ownership are explicit; lifecycle, authority, and data compatibility evidence passes. | -| Native Go client | PRs 7 and 8. | Client/server dependency is separated; Go clients, unchanged TypeScript SDK, reconnect, and cancellation acceptance passes. | -| Selected follow-ups | Each separately agreed actor, tracing, persistence, or cleanup change, or a small group defined before work starts. | The specific benefit is demonstrated and the same compatibility gates pass. No open-ended final stack. | - -At each checkpoint, review the combined result and decide whether the next -group still warrants its risk. Merge approved PRs bottom-up into development, -retargeting and rebasing descendants as needed. After each merge or rebase, -run the required checks on the resulting revision; verify the integrated -development revision before starting the next group. Preserve separate PR -review records. Do not auto-merge or use one final integration-only PR to -repair broken intermediate states. +| Prerequisites and guard | [299](https://github.com/context-labs/whip/pull/299) audit repair → [300](https://github.com/context-labs/whip/pull/300) stacked CI → [301](https://github.com/context-labs/whip/pull/301) credential isolation → [307](https://github.com/context-labs/whip/pull/307) dialog readiness → [302](https://github.com/context-labs/whip/pull/302) frozen guard. | Audit, full existing CI and calibrated fixed-client/data checks; review repairs separately from restructuring. | +| Provider responsibility | [304](https://github.com/context-labs/whip/pull/304) host MCP → [305](https://github.com/context-labs/whip/pull/305) operation boundary → [306](https://github.com/context-labs/whip/pull/306) test seams → [308](https://github.com/context-labs/whip/pull/308) provider package. | Configuration atomicity, provider semantics, lifecycle and unchanged clients. | +| Composition and resources | [309](https://github.com/context-labs/whip/pull/309) runtime factory → [310](https://github.com/context-labs/whip/pull/310) host directory → [311](https://github.com/context-labs/whip/pull/311) processes → [312](https://github.com/context-labs/whip/pull/312) workspaces. | Construction/failure/restart/shutdown characterizations, unchanged authority and data compatibility. | +| Later fixture prerequisites | [313](https://github.com/context-labs/whip/pull/313) gateway write/rejection ordering → [314](https://github.com/context-labs/whip/pull/314) performance receipt instrumentation. | Reproduce inherited failures; preserve original assertions and budgets. | +| Native clients | [315](https://github.com/context-labs/whip/pull/315) shared plumbing → [316](https://github.com/context-labs/whip/pull/316) tagged TUI title fixture → [317](https://github.com/context-labs/whip/pull/317) client package. | API/body/test conservation, TUI/PTY/ACP acceptance, fixed SDK, reconnect and cancellation. Review the fixture repair independently. | +| Bounded persistence and closeout | [318](https://github.com/context-labs/whip/pull/318) store lifecycle → this documentation-only closeout. | Same-package declaration conservation, integrated review-tip acceptance, fixed/immediate-base guard and explicit native limitations. | + +This is one unmerged chain; groups do not permit skipping prerequisites. After +human approval, merge approved PRs bottom-up into development, retargeting or +rebasing descendants as needed. Recheck changed ancestry and run the required +checks on the resulting revision, including fixed-reference and immediate-base +comparisons. Preserve individual review records. This execution verifies an +integrated review tip; verifying merged development is a later step after +authorized merges. Do not auto-merge or use a final integration-only PR to hide +broken intermediate states. Every PR description should contain: @@ -568,12 +599,13 @@ Local full-module build/vet/test checks complement hosted coverage; browser and TUI tests require their appropriate browser/TTY environment. Use targeted tests during edits and complete the required gate once the PR is ready. -Move existing tests with implementation only when necessary. Update -architecture tests to follow the new owners while preserving their assertions. -For example, provider-call checks currently scan the daemon directory and -name `agent_session.go`; after a relevant move, scanning only the old directory -could silently stop enforcing the boundary. Update coverage/package selection -to include new packages, not exclude moved code. +Move existing tests with implementation only when necessary. Keep architecture +scans, package selectors and named tests attached to their actual owner. A +successful selector against only the old package can silently omit a moved +assertion. The provider-call guard now scans daemon, provider and client while +retaining the exact `daemon/agent_session.go` exception; runtime and named +reconnect acceptance selectors include client. Existing coverage remains in +force for moved code. Add focused import checks for boundaries actually introduced: provider must not import daemon; client must not import the server implementation; storage @@ -625,7 +657,8 @@ the backend easier to work on enough to justify its review and regression risk. ## Research source map -Primary implementation references at the recorded revision: +Historical implementation references at the starting revision +`271c0f8d2a35648d1b45056d57432590b783483c` (moved paths are intentional): - Startup/lifecycle: `cmd/whip/daemon.go`, `internal/daemon/daemon.go`, `server.go`, `session.go`, `socket_unix.go`. @@ -651,7 +684,7 @@ prerequisite. The execution ledger below records subsequent repairs and results. All active review PRs remain unmerged. Rebased dependency heads are recorded below; successful checks on an earlier head are not a claim that a current-head rerun has finished. -The current order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 312 → 313 → 314 → 315 → 316 → native client extraction. +The implemented order is 299 → 300 → 301 → 307 → 302 → 304 → 305 → 306 → 308 → 309 → 310 → 311 → 312 → 313 → 314 → 315 → 316 → 317 → 318 → documentation closeout. The separate UI-readiness repair now precedes the compatibility gate so that PR #302 inherits that repair in its own required CI. The combined tree at the new PR #302 head is identical to the previous PR #303 tree; PRs #304–#306 and @@ -663,7 +696,12 @@ parent when the reordered parent contained its commit. Replacement PR #307 keeps that separate repair reviewable against PR #301. No merge command ran, and development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. -| Step | Revision and PR | Evidence and status | +The table and detailed entries preserve evidence as recorded during each step, +including historical failures and runs then pending. They are not a live hosted +status dashboard. Final closeout results are reported on the documentation PR +and in the handoff, with their exact heads/bases and remaining limits. + +| Step | Revision and PR | Evidence and status at recording | | --- | --- | --- | | Dependency-audit prerequisite | `db3a1cea247eee7cbaa0424fe3ee89eb0d36bf9d`, [PR #299](https://github.com/context-labs/whip/pull/299) | Only 11 `brace-expansion` lockfile entries changed. Local install, unchanged production-audit threshold, protocol freshness, 470 SDK unit tests, example build, and package smoke passed. [Full CI](https://github.com/context-labs/whip/actions/runs/36678816413) and security passed. This is the green maintenance base; the original development SDK remains the fixed oracle. | | Stacked-base CI prerequisite | `dba610243623b1a7f6f13f910ddec4d6df9bb711`, [PR #300](https://github.com/context-labs/whip/pull/300) | Only CI/security PR-base filters and their distribution-test expectation changed, plus this plan. All 36 distribution-policy tests and workflow validation passed. GitHub verified both workflows start against stacked bases. [Full current CI](https://github.com/context-labs/whip/actions/runs/36681079742) and current security passed. | @@ -677,13 +715,13 @@ development remains at `271c0f8d2a35648d1b45056d57432590b783483c`. | Startup factory extraction (plan PR 4a) | `b251786c8d868cba722f103d0a77ce72d07377f5`, [PR #309](https://github.com/context-labs/whip/pull/309). | The existing runtime factory and five helpers move to `cmd/whip/daemon_runtime.go`. Exact body comparison, full CLI race/shuffle (71.763s), module build/vet/whipvet, and fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36686776874) and [security](https://github.com/context-labs/whip/actions/runs/36686776543) started; results were pending when this entry was recorded. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | | Host directory grouping (plan PR 4b) | `774623f12ef182856862209d186bc70150d17cf1`, [PR #310](https://github.com/context-labs/whip/pull/310). | Four existing directory listing, creation and native-picker functions move to `internal/daemon/host_directory.go`. AST-directed extraction preserves all six original function declarations and comments, leaving host dispatch and attention in `host.go`. Existing host/directory/RPC race/shuffle tests (4.644s), module build/vet/whipvet and exact source comparison passed. Fresh fixed/immediate-base compatibility passed. [CI](https://github.com/context-labs/whip/actions/runs/36687285608) and [security](https://github.com/context-labs/whip/actions/runs/36687285375) were pending at publication. The current head includes the inherited header-spelling correction; earlier run results refer to the prior head. | | Process ownership (plan PR 5) | `42285977df445ac79334ac96e465d44f057f0350`, [PR #311](https://github.com/context-labs/whip/pull/311), based on PR #310. | Baseline lifecycle characterizations were committed and passed before production edits. Startup now constructs the shared manager explicitly and transfers ownership to the daemon only after successful construction. Validation and the detailed ownership map are recorded below. | -| Workspace ownership (plan PR 6) | `codex/backend-reorg-06-workspace-ownership`, based on PR #311 (`42285977df445ac79334ac96e465d44f057f0350`). | A green, mutation-calibrated composition test precedes the ownership change. Host startup supplies one coordinator to storage; existing root/child/tool borrowers retain the same accessor and implementation. Validation and the deliberate remaining dependency are recorded below. | +| Workspace ownership (plan PR 6) | `26a6fec9b505fd6c00cd10d64c753c779509a2a4`, [PR #312](https://github.com/context-labs/whip/pull/312), based on PR #311. | A green, mutation-calibrated composition test precedes the ownership change. Host startup supplies one coordinator to storage; existing root/child/tool borrowers retain the same accessor and implementation. Validation and the deliberate remaining dependency are recorded below. | | Gateway fixture synchronization | `067fe82cd90b99aed42efa80c24e3917ba96e820`, [PR #313](https://github.com/context-labs/whip/pull/313), following workspace ownership. | Eight test-only lines synchronize the two pipelined browser writes before backend rejection. Existing assertions remain exact; the detailed baseline diagnosis and checks are below. | -| Browser performance probe repair | `codex/backend-reorg-06b-performance-probe`, based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | +| Browser performance probe repair | `0081b66e5445b90d10e4d5ada7786335943a6edc`, [PR #314](https://github.com/context-labs/whip/pull/314), based on PR #313. | A separate instrumentation repair measures commit markers received in snapshots as well as notifications, preserving exact event sequences and first receipt. Focused negative-control regressions, full ordinary/controlled browser runs, and source conservation are recorded below. | | Shared native plumbing (plan PR 7) | `3127d8ef67c3d59cd70f55ad697102e275c2a6fc`, [PR #315](https://github.com/context-labs/whip/pull/315), based on PR #314. | Shared connection primitives and command presentation move without changing client/server policy. The declaration, characterization, full affected-suite and fresh fixed/immediate-base evidence is recorded below. The PR remains unmerged. | | Tagged TUI title fixture repair | `e289b4ea3344b6fdd45a8782d17c5c66084e90e4`, [PR #316](https://github.com/context-labs/whip/pull/316), based on PR #315. | Separate test-only prerequisite fixes a title-generation fixture that already failed on the starting revision's policy. Both transports retain the original final assertions; the existing tagged acceptance test is added to Linux/macOS runtime CI. Diagnosis and evidence are recorded below. | | Native client extraction (plan PR 8) | `d36711aeaf48257025107dd4552f777854010f50`, [PR #317](https://github.com/context-labs/whip/pull/317), based on PR #316. | Exact implementation/private-test moves and canonical Go imports preserve all client APIs, bodies and assertions. Full affected race/PTY suites, named native acceptance and static checks passed. After the separate inherited title-fixture repair, the tagged TUI gate and refreshed fixed/immediate-parent guard passed at clean code commit `ecf96616acf48233658620c81286a08fd9bada80`; final documentation records the complete evidence below. | -| Store lifecycle grouping (plan PR 9) | `codex/backend-reorg-09-store-lifecycle`, based on PR #317 (`d36711aeaf48257025107dd4552f777854010f50`). | Five unchanged declarations and their comments move into `internal/session/store.go`; all 58 remaining declarations are preserved. Connection setup, borrowed references, the daemon guard and database closure now have one small source home. Detailed conservation and validation evidence is recorded below. | +| Store lifecycle grouping (plan PR 9) | `882d1377800830c2723161d2b6f0a5e7db68ee6f`, [PR #318](https://github.com/context-labs/whip/pull/318), based on PR #317. | Five unchanged declarations and their comments move into `internal/session/store.go`; all 58 remaining declarations are preserved. Connection setup, borrowed references, the daemon guard and database closure now have one small source home. Detailed conservation and validation evidence is recorded below. | Fresh post-reorder evidence is recorded at `/private/tmp/whip-reorg-03b2-published-compat-evidence/evidence.json`: fixed @@ -1467,3 +1505,88 @@ installation; recorded timestamps confirm no concurrent installation or build in that directory (`/private/tmp/whip-pr9-installer-timing.json`). Hosted checks will record the submitted commit and actual PR base separately. This PR remains unmerged pending human review. + + +### Documentation closeout and integrated review tip + +This closeout changes only the canonical architecture guide, this plan and the +historical redesign status pointer. It is based on the clean implementation tip +[PR #318](https://github.com/context-labs/whip/pull/318), +`882d1377800830c2723161d2b6f0a5e7db68ee6f`; it does not claim that its own eventual +commit was the subject of an earlier run. Development remains at the original +`271c0f8d2a35648d1b45056d57432590b783483c`. All active PRs are unmerged and await +human review. Historical PR #303 was marked merged into a former stack parent, +not development; active PR #307 replaces it. + +The completed improvement is concrete responsibility and ownership: + +- Provider setup has one package without a daemon import; unrelated host MCP + imports and icons have a server-owned component. Atomic host updates and + provisioning locks remain intact. +- Native Go client, TUI and ACP production code no longer imports server implementation. + Integration tests retain real daemon fixtures where required. Shared + connection primitives and one stored-result decoder have narrow homes; + canonical `CreateSession` identity is retained with aliases, not conversion. +- Startup visibly constructs the runtime factory and shared resources. Failed + construction, successful ownership transfer, root-only cleanup and final + manager-before-database shutdown have before-change characterizations. +- Store lifecycle has one small same-package source home. SQL, migrations, + permission transactions, root/child scheduling and tracing stay where their + existing boundaries require them. + +Move-aware declaration/API/comment/test proofs in the per-PR entries establish +mechanical conservation; file/line counts are relocation metrics, not evidence +of deleted complexity. The dependency and ownership changes above are the +reason to keep the work. Protocol still depends on existing domain values and +storage still borrows the workspace coordinator. No new actor, universal +resource registry, duplicate mutable projection or translation layer was added. +Further actor/tracing extraction is deferred because no equally useful safe +seam was established, not because protocol redesign is required to gain value. + +The final static audit at the implementation tip found zero drift in +`packages/sdk`, `packages/protocol`, `internal/protocol`, +`internal/protocoltransport`, the contract generator, or schema/migration +sources. `internal/rlm`, `internal/llm` and the existing daemon/session span +sources are also unchanged. Protocol **6.9**, schema **21**, recognized historical +upgrade paths, both execution engines and tracing remain the existing +implementation. The lockfile change is limited to the 11 `brace-expansion` +entries in the independent audit repair. Frontend changes are the separately +reviewed fixture/probe repairs and one moved-source reference comment, not +product changes. Audit: `/private/tmp/whip-final-source-audit.json`. + +The latest structural compatibility evidence is the fresh PR #318 run at +`/private/tmp/whip-pr9-compat-fresh/evidence.json`, detailed above. It compares +the fixed starting SDK/backend and exact PR #317 parent against the staged +candidate implementation, with current sources conserved into the final +implementation tip. Its schema-21 binary rollback checks do not claim downgrade +through older one-way migrations. + +Final integrated `task acceptance` passed on clean implementation tip +`882d1377800830c2723161d2b6f0a5e7db68ee6f` in a real PTY, from 09:50:53 to +09:53:53 UTC on September 30 (180.15 seconds). Every command in that existing +target passed, including all 49 SDK acceptance cases (zero failures or skips), +packed-SDK imports outside the repository, checkpoint/model/pricing/usage checks +and native CLI/TUI/ACP/runtime gates. `npm run check:web` and web packaging +completed before that run. No global skip flag or live provider credentials +were used. Evidence: `/private/tmp/whip-final-acceptance-result.json` and +`/private/tmp/whip-final-acceptance.log`. Hosted closeout results remain pending +at documentation preparation and must be supplied with the exact head/base in +the PR/handoff; local acceptance does not stand in for hosted CI. + +Native browser evidence was collected at PR #315 +(`3127d8ef67c3d59cd70f55ad697102e275c2a6fc`); all 49 relevant source/dependency +hashes match the implementation tip. A disposable Electron 44.2.0 fixture +passed 20 checks, and `TestDesktopNativeRod` passed with race instrumentation. +The browser/extrelay race/shuffle suites passed 46 top-level tests, including +the real headed Chrome-for-Testing extension fixture: 47 native Go tests passed +in total. `TestDriverParity` skipped because it assumes Linux browser paths +unavailable on macOS. Native guest/BrowserWindow capture passed; OS compositor +capture was unavailable because macOS screen permission was denied. No user +browser, installed daemon or permission setting was changed; fixture cleanup +was verified. Evidence: `/private/tmp/whip-native-acceptance-315/report.md` and +`source-hashes.json` in that directory. + +The separately repaired tagged TUI title acceptance passes on both transports. +An optional supplemental lint run with integration tags still reports inherited +`noctx` in the TUI fixture; required default lint passes. This limitation, +the platform skip and unavailable compositor capture are not recorded as passes. From d29344dcf638a9b992fe6640b74e17d832efd5d3 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 10:03:26 -0700 Subject: [PATCH 52/67] docs: consolidate backend reorganization review --- docs/backend-reorganization-plan.md | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/backend-reorganization-plan.md b/docs/backend-reorganization-plan.md index 6d925a19d..c33c4391c 100644 --- a/docs/backend-reorganization-plan.md +++ b/docs/backend-reorganization-plan.md @@ -1,9 +1,24 @@ # Backend reorganization with a frozen client contract -Status: structural work complete; documentation prepared for human review. -All active PRs remain unmerged. Final local integrated acceptance passed on the -implementation tip below. Hosted closeout checks are pending as of this record; -completed hosted results belong in the closeout PR and final handoff. +Status: structural work and documentation complete; awaiting holistic human +review in one combined PR against `development`, on +`codex/backend-reorg-combined`. Nothing is authorized to merge yet. + +Review instruction, September 30: after an initial Desktop review, the user +requested consolidation of the completed stack into a single PR. This supersedes +the delivery and checkpoint-merge cadence below. Preserve all 30 original +commits, including the separately proposed dependency and test-fixture repairs; +close the superseded review PRs while retaining their branches and review +history. The implementation, frozen baseline, and compatibility constraints do +not change. This consolidation adds only this documentation update to the +tested stack tip `529026159836fee4f74bd3cd117c937f64dee147`. + +The original stack's final [CI](https://github.com/context-labs/whip/actions/runs/36699507090) +and [Security](https://github.com/context-labs/whip/actions/runs/36699506671) +passed. The combined PR requires fresh checks against `development`; its live +results belong in that PR. The sequential PR navigation, checkpoint instructions, +and evidence ledger below record implementation history, not additional active +merge targets. Earlier "pending" entries retain the status at recording time. Implementation review tip: [`882d1377800830c2723161d2b6f0a5e7db68ee6f`](https://github.com/context-labs/whip/commit/882d1377800830c2723161d2b6f0a5e7db68ee6f), [PR #318](https://github.com/context-labs/whip/pull/318). This documentation-only @@ -546,6 +561,11 @@ pointed-to resource becomes available or ceases to be usable. ## 8. PR, CI, and review policy +**Current review delivery:** the September 30 instruction above replaces the +stacked merge cadence in this section with one combined PR against +`development`. The original PRs remain references for focused diffs and evidence. +All compatibility gates still apply; consolidation does not authorize a merge. + This execution prepares one sequential review stack on `codex/backend-reorg-<step>-<topic>` branches. Every successor targets its immediate parent's branch, including across checkpoint groups. Each structural From ba1280c7957b613f64e717f6fdc0d6a3c776e5ef Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 11:28:48 -0700 Subject: [PATCH 53/67] refactor(tui): derive fallback effort levels from completion choices --- internal/tui/effort.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/tui/effort.go b/internal/tui/effort.go index 3cf857a24..b25bcd3e9 100644 --- a/internal/tui/effort.go +++ b/internal/tui/effort.go @@ -6,10 +6,6 @@ import ( "github.com/context-labs/whip/internal/config" ) -// defaultEfforts are the fallback levels when the provider doesn't advertise -// supported reasoning efforts. "off" sends no reasoning parameter. -var defaultEfforts = []string{"off", "low", "medium", "high"} - // effortCands completes /effort for models without advertised levels. var effortCands = []cand{ {"off", "No reasoning effort parameter sent"}, @@ -18,6 +14,16 @@ var effortCands = []cand{ {"high", "Deep reasoning, slower"}, } +// defaultEfforts uses the same fallback levels and order as completion. +// "off" sends no reasoning parameter. +var defaultEfforts = func() []string { + levels := make([]string, len(effortCands)) + for i, candidate := range effortCands { + levels[i] = candidate.Text + } + return levels +}() + // effortsFor returns the cycle of effort levels available for the current // model: the provider-advertised levels if known (each prefixed by off), else // the defaults. From 6d49db01528a1a44a0a77a86d1b0be46a892fe30 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 11:28:13 -0700 Subject: [PATCH 54/67] refactor(app): reuse SDK trace span types --- packages/app/src/trace-math.ts | 23 ++++------------------- packages/app/src/trace-view.tsx | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/packages/app/src/trace-math.ts b/packages/app/src/trace-math.ts index 12c400143..3a7137833 100644 --- a/packages/app/src/trace-math.ts +++ b/packages/app/src/trace-math.ts @@ -1,23 +1,8 @@ -// Layout math follows HALO's trace viewer (timelineMath, spanTree, rollups), ported to Whip spans. +import type { TraceSpan } from '@whip/sdk/state'; -export type TraceSpanKind = 'agent' | 'llm' | 'tool' | 'host' | 'wait'; -export type TraceSpanStatus = 'running' | 'ok' | 'error' | 'cancelled' | 'interrupted'; -export interface TraceSpan { - readonly id: string; - readonly traceId: string; - readonly parentId: string; // '' for a trace root - readonly rootId: string; - readonly agentId: string; - readonly turnId: string; - readonly kind: TraceSpanKind; - readonly name: string; - readonly status: TraceSpanStatus; - readonly startMs: number; // wall clock, ms since epoch, fractional allowed - readonly endMs: number; // 0 while the span is still open - readonly attrs: Readonly<Record<string, unknown>>; // whip-native keys, see below - readonly links: readonly { readonly traceId: string; readonly spanId: string }[]; - readonly updatedSeq: string; -} +export type { TraceSpan, TraceSpanKind, TraceSpanStatus } from '@whip/sdk/state'; + +// Layout math follows HALO's trace viewer (timelineMath, spanTree, rollups), ported to Whip spans. export interface TraceNode { readonly span: TraceSpan; readonly children: readonly TraceNode[]; readonly depth: number } /** Visible time window, in ms relative to the domain start. */ diff --git a/packages/app/src/trace-view.tsx b/packages/app/src/trace-view.tsx index 4d292f4b2..0804f268e 100644 --- a/packages/app/src/trace-view.tsx +++ b/packages/app/src/trace-view.tsx @@ -48,7 +48,7 @@ export function TraceView({ view, state, runtimeId, viewId, connected }: { const roots = useMemo(() => traceRoots(state), [state]); const [picked, setPicked] = useState<string>(); const traceId = picked && (picked === ALL_TRACES || roots.some(root => root.traceId === picked)) ? picked : roots[0]?.traceId ?? ''; - const spans = useMemo(() => traceSpans(state, traceId === ALL_TRACES ? undefined : traceId) as readonly TraceSpan[], [state, traceId]); + const spans = useMemo(() => traceSpans(state, traceId === ALL_TRACES ? undefined : traceId), [state, traceId]); const running = connected && spans.some(isSpanInFlight); const motion = useTranscriptMotion(); const [now, setNow] = useState(() => serverNowMs(evidence)); From 7f5753d13f026d4af41f3ba9e1b69c691f887971 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 11:30:19 -0700 Subject: [PATCH 55/67] Reuse MCP status projection and guard mirrored data contracts --- internal/daemon/client_control.go | 9 +- internal/daemon/client_control_mcp_test.go | 96 ++++++++++++++++++++++ internal/mcp/config_contract_test.go | 84 +++++++++++++++++++ internal/provider/provider_catalog_test.go | 38 +++++++++ 4 files changed, 219 insertions(+), 8 deletions(-) create mode 100644 internal/daemon/client_control_mcp_test.go create mode 100644 internal/mcp/config_contract_test.go create mode 100644 internal/provider/provider_catalog_test.go diff --git a/internal/daemon/client_control.go b/internal/daemon/client_control.go index f291d3464..991952108 100644 --- a/internal/daemon/client_control.go +++ b/internal/daemon/client_control.go @@ -1272,14 +1272,7 @@ func (s *Session) clientMCP(ctx context.Context, operation string, payload clien statuses := append(manager.Statuses(), manager.Blocked()...) statuses = append(statuses, manager.SourceErrors()...) slices.SortFunc(statuses, func(a, b mcp.Server) int { return strings.Compare(a.Name, b.Name) }) - result := make([]MCPStatusResult, 0, len(statuses)) - for _, status := range statuses { - result = append(result, MCPStatusResult{ - Name: status.Name, Status: status.Status.String(), Note: status.Note, - Error: status.Err, Tools: status.Tools, Source: status.Source, - }) - } - return marshalClientOutput(result, nil) + return marshalClientOutput(mcp.ServerStatuses(statuses), nil) } return applyMCPAction(manager, operation, payload.Name) } diff --git a/internal/daemon/client_control_mcp_test.go b/internal/daemon/client_control_mcp_test.go new file mode 100644 index 000000000..6e8c1bc71 --- /dev/null +++ b/internal/daemon/client_control_mcp_test.go @@ -0,0 +1,96 @@ +package daemon + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/context-labs/whip/internal/mcp" + "github.com/context-labs/whip/internal/protocol" +) + +type statusSurfaceMCP struct { + controlSurfaceMCP + live, blocked, sourceErrors []mcp.Server +} + +func (m *statusSurfaceMCP) Statuses() []mcp.Server { return m.live } +func (m *statusSurfaceMCP) Blocked() []mcp.Server { return m.blocked } +func (m *statusSurfaceMCP) SourceErrors() []mcp.Server { return m.sourceErrors } + +func TestClientMCPStatusJSON(t *testing.T) { + for _, test := range []struct { + name string + manager *statusSurfaceMCP + want string + }{ + {name: "empty", manager: &statusSurfaceMCP{}, want: "[]"}, + { + name: "sorted live and discovery rows", + manager: &statusSurfaceMCP{ + live: []mcp.Server{{Name: "z-live", Status: mcp.StatusReady, Tools: 2}}, + blocked: []mcp.Server{{Name: "b-blocked", Status: mcp.StatusBlocked, Note: "import disabled", Source: "project"}}, + sourceErrors: []mcp.Server{{Name: "a-source", Status: mcp.StatusUnreadable, Err: "unreadable", Source: "config"}}, + }, + want: `[{"name":"a-source","status":"unreadable","error":"unreadable","source":"config"},{"name":"b-blocked","status":"blocked","note":"import disabled","source":"project"},{"name":"z-live","status":"ready","tools":2}]`, + }, + } { + t.Run(test.name, func(t *testing.T) { + root := &Session{mcp: test.manager} + got, err := root.clientMCP(t.Context(), "mcp.status", clientActionPayload{}) + if err != nil || got != test.want { + t.Fatalf("status = %s, %v; want %s", got, err, test.want) + } + }) + } +} + +// Runtime MCP results are serialized directly. Keep their independently owned +// protocol declarations aligned without making either package depend on a copy. +func TestMCPResultContractParity(t *testing.T) { + for _, test := range []struct { + name string + runtime, wire reflect.Type + }{ + {"status", reflect.TypeFor[mcp.ServerStatus](), reflect.TypeFor[protocol.MCPStatusResult]()}, + {"refresh", reflect.TypeFor[mcp.RefreshResult](), reflect.TypeFor[protocol.MCPRefreshResult]()}, + } { + t.Run(test.name, func(t *testing.T) { + if test.runtime.NumField() != test.wire.NumField() { + t.Fatal("runtime and wire result fields differ") + } + for i := range test.runtime.NumField() { + a, b := test.runtime.Field(i), test.wire.Field(i) + if a.Type == reflect.TypeFor[[]mcp.ServerStatus]() { + a.Type = reflect.TypeFor[[]protocol.MCPStatusResult]() + } + if a.Name != b.Name || a.Type != b.Type || a.Tag != b.Tag { + t.Errorf("field %d differs: %v / %v", i, a, b) + } + } + }) + } + for _, test := range []struct { + name string + result mcp.RefreshResult + }{ + {name: "nil slices"}, + {name: "empty slices", result: mcp.RefreshResult{Added: []string{}, Existing: []string{}, Changed: []string{}, Servers: []mcp.ServerStatus{}, Blocked: []mcp.ServerStatus{}, SourceErrors: []mcp.ServerStatus{}}}, + {name: "populated", result: mcp.RefreshResult{Added: []string{"new"}, Existing: []string{"old"}, Changed: []string{"changed"}, Servers: []mcp.ServerStatus{{Name: "new", Status: "ready", Tools: 2}}, Blocked: []mcp.ServerStatus{{Name: "blocked", Status: "blocked", Note: "disabled", Source: "project"}}, SourceErrors: []mcp.ServerStatus{{Name: "source", Status: "unreadable", Error: "failed", Source: "config"}}}}, + } { + t.Run(test.name, func(t *testing.T) { + raw, err := json.Marshal(test.result) + if err != nil { + t.Fatal(err) + } + var wire protocol.MCPRefreshResult + if err := json.Unmarshal(raw, &wire); err != nil { + t.Fatal(err) + } + roundTrip, err := json.Marshal(wire) + if err != nil || string(raw) != string(roundTrip) { + t.Fatalf("MCP result changed through protocol: %s => %s, %v", raw, roundTrip, err) + } + }) + } +} diff --git a/internal/mcp/config_contract_test.go b/internal/mcp/config_contract_test.go new file mode 100644 index 000000000..2a0b86071 --- /dev/null +++ b/internal/mcp/config_contract_test.go @@ -0,0 +1,84 @@ +package mcp_test + +import ( + "encoding/json" + "reflect" + "testing" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/mcp" + "github.com/context-labs/whip/internal/protocol" +) + +func TestMCPConfigContractParity(t *testing.T) { + savedType := reflect.TypeFor[config.MCPServer]() + runtimeType := reflect.TypeFor[mcp.ServerConfig]() + wireType := reflect.TypeFor[protocol.MCPServerConfig]() + if savedType.NumField()+1 != runtimeType.NumField() || wireType.NumField() != runtimeType.NumField() { + t.Fatal("MCP config shapes differ beyond runtime-only trust") + } + for i := range runtimeType.NumField() { + field := runtimeType.Field(i) + wire, ok := wireType.FieldByName(field.Name) + wantTag := field.Tag + switch field.Name { + case "StartupTimeout": + wantTag = `json:"startup_timeout,omitempty"` + case "ToolTimeout": + wantTag = `json:"tool_timeout,omitempty"` + } + if !ok || wire.Type != field.Type || wire.Tag != wantTag { + t.Errorf("wire field %s no longer matches runtime config", field.Name) + } + if field.Name == "Trusted" { + if field.Tag.Get("json") != "-" { + t.Fatal("runtime trust must not be serialized") + } + continue + } + saved, ok := savedType.FieldByName(field.Name) + if !ok || saved.Type != field.Type || saved.Tag != field.Tag { + t.Errorf("persisted field %s no longer matches runtime config", field.Name) + } + } + + // Populate every saved field so adding one cannot silently bypass the + // hand-written persistence-to-runtime projection. + saved := config.MCPServer{ + Origin: "claude", Source: "project/.mcp.json", Command: []string{"fixture", "--arg"}, + Env: map[string]string{"KEY": "$REFERENCE"}, Cwd: "/project", URL: "https://example.invalid/mcp", + Headers: map[string]string{"Authorization": "$TOKEN"}, Enabled: new(false), Note: "fixture", + StartupTimeout: 17, ToolTimeout: 23, + } + for i := range savedType.NumField() { + if reflect.ValueOf(saved).Field(i).IsZero() { + t.Fatalf("populate new config field %s to cover its conversion", savedType.Field(i).Name) + } + } + raw, err := json.Marshal(saved) + if err != nil { + t.Fatal(err) + } + var want mcp.ServerConfig + if err := json.Unmarshal(raw, &want); err != nil { + t.Fatal(err) + } + got := mcp.FromConfigMap(map[string]config.MCPServer{"fixture": saved})["fixture"] + if !reflect.DeepEqual(got, want) { + t.Fatalf("saved config lost fields: got %+v; want %+v", got, want) + } + + got.Trusted = true + encoded, err := json.Marshal(protocol.MCPAttachParams{Servers: map[string]mcp.ServerConfig{"fixture": got}}) + if err != nil { + t.Fatal(err) + } + // Reuse a previously trusted object, just as a long-lived decoder could. + decoded := protocol.MCPAttachParams{Servers: map[string]mcp.ServerConfig{"fixture": got}} + if err := json.Unmarshal(encoded, &decoded); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(decoded.Servers["fixture"], want) { + t.Fatalf("wire conversion lost config or conveyed trust: %+v", decoded.Servers["fixture"]) + } +} diff --git a/internal/provider/provider_catalog_test.go b/internal/provider/provider_catalog_test.go new file mode 100644 index 000000000..b9a6e5e5f --- /dev/null +++ b/internal/provider/provider_catalog_test.go @@ -0,0 +1,38 @@ +package provider + +import ( + "reflect" + "testing" + + "github.com/context-labs/whip/internal/config" + "github.com/context-labs/whip/internal/llm" +) + +func TestModelInfoLitesPreservesAdvertisedMetadata(t *testing.T) { + for _, test := range []struct { + name string + input []llm.ModelInfo + want []config.ModelInfoLite + }{ + {name: "absent catalog", want: []config.ModelInfoLite{}}, + {name: "empty catalog", input: []llm.ModelInfo{}, want: []config.ModelInfoLite{}}, + {name: "unknown metadata", input: []llm.ModelInfo{{ID: "unknown"}}, want: []config.ModelInfoLite{{ID: "unknown"}}}, + { + name: "explicitly empty capabilities and free pricing", + input: []llm.ModelInfo{{ID: "free", ReasoningEfforts: []string{}, InputModalities: []string{}, Pricing: &llm.Pricing{Prompt: "0", Completion: "0", InputCacheRead: "0"}}}, + want: []config.ModelInfoLite{{ID: "free", ReasoningEfforts: []string{}, InputModalities: []string{}, Pricing: llm.Pricing{Prompt: "0", Completion: "0", InputCacheRead: "0"}}}, + }, + { + name: "exact pricing and provider order", + input: []llm.ModelInfo{{ID: "z", ContextLength: 1234, MaxCompletionTokens: 567, ReasoningEfforts: []string{"future", "high"}, InputModalities: []string{"image", "text"}, Pricing: &llm.Pricing{Prompt: "0.1234567890123456789012345678", Completion: "0.000005", InputCacheRead: "0"}}, {ID: "a", Pricing: &llm.Pricing{Prompt: "0"}}}, + want: []config.ModelInfoLite{{ID: "z", ContextLength: 1234, MaxCompletionTokens: 567, ReasoningEfforts: []string{"future", "high"}, InputModalities: []string{"image", "text"}, Pricing: llm.Pricing{Prompt: "0.1234567890123456789012345678", Completion: "0.000005", InputCacheRead: "0"}}, {ID: "a", Pricing: llm.Pricing{Prompt: "0"}}}, + }, + } { + t.Run(test.name, func(t *testing.T) { + got := modelInfoLites(test.input) + if !reflect.DeepEqual(got, test.want) { + t.Fatalf("cached models = %#v; want %#v", got, test.want) + } + }) + } +} From 6e2bfe58c217a2e5e7fafc0224d947f2526027f0 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 11:33:05 -0700 Subject: [PATCH 56/67] refactor: centralize lifecycle status predicates --- internal/client/root_client.go | 5 +- internal/client/root_client_test.go | 82 ++++++++++++++ internal/daemon/session.go | 6 +- internal/session/agent_turn.go | 2 +- internal/session/capability.go | 3 +- internal/session/command.go | 11 ++ internal/session/runtime.go | 6 +- internal/session/runtime_status_test.go | 139 ++++++++++++++++++++++++ internal/session/turn_outcome.go | 18 ++- 9 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 internal/session/runtime_status_test.go diff --git a/internal/client/root_client.go b/internal/client/root_client.go index 8c180e5d8..b89fb9785 100644 --- a/internal/client/root_client.go +++ b/internal/client/root_client.go @@ -323,7 +323,7 @@ func (c *RootClient) Command(ctx context.Context, action RootAction) (protocol.C CommandID: action.CommandID, Scope: string(session.CommandScopeRoot), RootID: action.RootID, Operation: action.Operation, Payload: action.Payload, }) - if tracked && (result.Status == "succeeded" || result.Status == "failed" || result.Status == "cancelled" || result.Status == "interrupted") { + if tracked && session.IsTerminalCommandStatus(result.Status) { c.mu.Lock() if c.submittedCommands[action.RootID] == action.CommandID { delete(c.submittedCommands, action.RootID) @@ -647,8 +647,7 @@ func (c *RootClient) emitEvent(event protocol.ProtocolEvent) bool { c.activeTurns[lifecycle.AgentID] = lifecycle.TurnID } if strings.HasPrefix(event.Kind, "turn.") || strings.HasPrefix(event.Kind, "agent.turn.") { - switch lifecycle.Status { - case "succeeded", "failed", "cancelled", "interrupted": + if session.IsTerminalTurnStatus(lifecycle.Status) { delete(c.activeTurns, lifecycle.AgentID) } } diff --git a/internal/client/root_client_test.go b/internal/client/root_client_test.go index 0794757c9..e8c94a25d 100644 --- a/internal/client/root_client_test.go +++ b/internal/client/root_client_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "fmt" "net" "sync" "testing" @@ -13,6 +14,87 @@ import ( "github.com/context-labs/whip/internal/session" ) +type statusRootConnection struct { + *staticRootConnection + status string +} + +func (c *statusRootConnection) Command(_ context.Context, params protocol.CommandParams) (protocol.CommandResult, error) { + return protocol.CommandResult{CommandID: params.CommandID, Status: c.status}, nil +} + +func TestRootClientCancellationTargetsPreserveStatusBoundaries(t *testing.T) { + for _, test := range []struct { + status string + terminal bool + }{ + {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, + {"queued", false}, {"running", false}, {"waiting", false}, + {"stopped", false}, {"deleted", false}, {"unknown", false}, + {"", false}, {"Succeeded", false}, {" succeeded", false}, + } { + t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { + connection := &statusRootConnection{staticRootConnection: newStaticRootConnection(), status: test.status} + client, err := NewRootClient(RootClientOptions{ + ClientID: "client", RootID: "root", + Connector: func(context.Context, map[string]int64) (RootConnection, error) { return connection, nil }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = client.Close() }) + client.state, client.conn = RootLive, connection + for index, event := range []struct{ kind, status string }{ + {"turn.started", "running"}, {"turn." + test.status, test.status}, + } { + body, err := json.Marshal(session.LifecycleEvent{AgentID: "root", TurnID: "turn", Status: event.status}) + if err != nil { + t.Fatal(err) + } + if !client.emitEvent(protocol.ProtocolEvent{RootID: "root", Seq: int64(index + 1), Kind: event.kind, Payload: body}) { + t.Fatal("event was not accepted") + } + } + cancel, err := client.NewAction("cancel", nil) + if err != nil { + t.Fatal(err) + } + var target struct { + TurnID string `json:"turn_id"` + TargetCommandID string `json:"target_command_id"` + } + if err := json.Unmarshal(cancel.Payload, &target); err != nil { + t.Fatal(err) + } + wantTurn := "turn" + if test.terminal { + wantTurn = "" + } + if target.TurnID != wantTurn || target.TargetCommandID != "" { + t.Fatalf("turn cancellation = %+v; want turn %q", target, wantTurn) + } + if _, err := client.Command(t.Context(), RootAction{CommandID: "command", Operation: "submit", RootID: "root"}); err != nil { + t.Fatal(err) + } + cancel, err = client.NewAction("cancel", nil) + if err != nil { + t.Fatal(err) + } + target.TurnID, target.TargetCommandID = "", "" + if err := json.Unmarshal(cancel.Payload, &target); err != nil { + t.Fatal(err) + } + wantCommand := "command" + if test.terminal { + wantCommand = "" + } + if target.TargetCommandID != wantCommand || target.TurnID != "" { + t.Fatalf("command cancellation = %+v; want command %q", target, wantCommand) + } + }) + } +} + type deferredRootConnection struct { *staticRootConnection commands chan protocol.CommandParams diff --git a/internal/daemon/session.go b/internal/daemon/session.go index 0a40e69d0..7c0809fe0 100644 --- a/internal/daemon/session.go +++ b/internal/daemon/session.go @@ -454,10 +454,10 @@ func (s *Session) admitCommand(ctx context.Context, admission sessionstore.Comma return admittedCommand{result: result}, nil } receipt := newReceipt(result.Command.IngressSeq) - switch result.Command.Status { - case "queued", "running", "waiting": + switch { + case result.Command.Status == "queued" || result.Command.Status == "running" || result.Command.Status == "waiting": s.register(receipt) - case "succeeded", "failed", "cancelled", "interrupted": + case sessionstore.IsTerminalCommandStatus(result.Command.Status): output, resolveErr := s.store.ResolveRuntimeValue(actorCtx, s.id, result.Command.Outcome) if resolveErr != nil { receipt.finish(Completion{Sequence: result.Command.IngressSeq, Err: resolveErr}) diff --git a/internal/session/agent_turn.go b/internal/session/agent_turn.go index 62bb9f951..f4fc16e39 100644 --- a/internal/session/agent_turn.go +++ b/internal/session/agent_turn.go @@ -162,7 +162,7 @@ func (s *Store) StartAgentTurn(ctx context.Context, rootID, agentID, turnID stri // success, failure, cancellation, and interruption all return it to idle. func (s *Store) FinishAgentTurn(ctx context.Context, rootID, agentID string, commit AgentTurnCommit) error { status := commit.Status - if status != "succeeded" && status != "failed" && status != "cancelled" && status != "interrupted" { + if !IsTerminalTurnStatus(status) { return fmt.Errorf("invalid turn status %q", status) } if commit.TurnID == "" { diff --git a/internal/session/capability.go b/internal/session/capability.go index c8457e25a..1fe531e26 100644 --- a/internal/session/capability.go +++ b/internal/session/capability.go @@ -392,8 +392,7 @@ func (s *Store) ensureAuthority(ctx context.Context, rootID string, authority ca if err := tx.QueryRowContext(ctx, `SELECT status FROM agents WHERE id=? AND root_id=?`, authority.AgentID, rootID).Scan(&status); err != nil { return capability.Authority{}, err } - switch status { - case "failed", "stopped", "cancelled", "interrupted", "deleted", "succeeded": + if isTerminalAgentStatus(status) { return capability.Authority{}, ErrRootTerminal } for _, grant := range []struct { diff --git a/internal/session/command.go b/internal/session/command.go index 06bf67060..1c6ba3089 100644 --- a/internal/session/command.go +++ b/internal/session/command.go @@ -36,6 +36,17 @@ type CommandRecord struct { Outcome RuntimeValue } +// IsTerminalCommandStatus reports whether status is a completed command outcome. +// Unknown statuses are neither terminal nor an assertion that a command is pending. +func IsTerminalCommandStatus(status string) bool { + switch status { + case "succeeded", "failed", "cancelled", "interrupted": + return true + default: + return false + } +} + type CommandAdmissionResult struct { Command CommandRecord EventSeq int64 diff --git a/internal/session/runtime.go b/internal/session/runtime.go index 9458ea943..05688354c 100644 --- a/internal/session/runtime.go +++ b/internal/session/runtime.go @@ -621,7 +621,7 @@ func (s *Store) commitRootTurn(ctx context.Context, commit RootTurnCommit, befor status = "failed" } } - if status != "succeeded" && status != "failed" && status != "cancelled" && status != "interrupted" { + if !IsTerminalTurnStatus(status) { return fmt.Errorf("invalid root turn status %q", status) } eventKind := "turn." + status @@ -1124,7 +1124,7 @@ func (s *Store) enqueueInboxTx(ctx context.Context, tx *sql.Tx, item InboxEnqueu if err := tx.QueryRowContext(ctx, `SELECT status FROM agents WHERE root_id=? AND id=?`, item.RootID, item.AgentID).Scan(&status); err != nil { return InboxSequence{}, err } - if status == "failed" || status == "stopped" || status == "cancelled" || status == "interrupted" || status == "deleted" || status == "succeeded" { + if isTerminalAgentStatus(status) { return InboxSequence{}, ErrRootTerminal } var sequence InboxSequence @@ -1375,7 +1375,7 @@ func (s *Store) commitRuntime(ctx context.Context, transition RuntimeTransition, } func (s *Store) FinishCommand(ctx context.Context, clientID, commandID, status string, outcome RuntimePayload) (RuntimeValue, error) { - if status != "succeeded" && status != "failed" && status != "cancelled" && status != "interrupted" { + if !IsTerminalCommandStatus(status) { return RuntimeValue{}, fmt.Errorf("command outcome status %q is not terminal", status) } var scope CommandScope diff --git a/internal/session/runtime_status_test.go b/internal/session/runtime_status_test.go new file mode 100644 index 000000000..2d78bb4ff --- /dev/null +++ b/internal/session/runtime_status_test.go @@ -0,0 +1,139 @@ +package session + +import ( + "errors" + "fmt" + "testing" +) + +func TestTurnAndCommandOutcomeStatusBoundaries(t *testing.T) { + for _, test := range []struct { + status string + terminal bool + }{ + {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, + {"queued", false}, {"running", false}, {"waiting", false}, {"idle", false}, + {"stopped", false}, {"deleted", false}, {"unknown", false}, + {"", false}, {"Succeeded", false}, {" succeeded", false}, + } { + t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + if _, err := store.AdmitCommand(t.Context(), CommandAdmission{ + ClientID: "client", CommandID: "command", Scope: CommandScopeDaemon, RequestDigest: "digest", + }); err != nil { + t.Fatal(err) + } + _, err := store.FinishCommand(t.Context(), "client", "command", test.status, RuntimePayload{}) + if test.terminal { + if err != nil { + t.Fatal(err) + } + } else if want := fmt.Sprintf("command outcome status %q is not terminal", test.status); err == nil || err.Error() != want { + t.Fatalf("command error = %v; want %q", err, want) + } + command, err := store.LoadCommand(t.Context(), "client", "command") + if err != nil { + t.Fatal(err) + } + wantCommand := "queued" + if test.terminal { + wantCommand = test.status + } + if command.Status != wantCommand { + t.Fatalf("command status = %q; want %q", command.Status, wantCommand) + } + + admitTestChild(t, store, root, agent, "child") + queueOutcomeTurn(t, store, root, "child", "child-turn") + err = store.FinishAgentTurn(t.Context(), root, "child", AgentTurnCommit{TurnID: "child-turn", Status: test.status}) + if test.terminal { + if err != nil { + t.Fatal(err) + } + } else if want := fmt.Sprintf("invalid turn status %q", test.status); err == nil || err.Error() != want { + t.Fatalf("child turn error = %v; want %q", err, want) + } + child, err := store.LoadAgent(t.Context(), root, "child") + if err != nil { + t.Fatal(err) + } + wantAgent, wantTurn := "running", "running" + if test.terminal { + wantAgent, wantTurn = "idle", test.status + } + if outcome := savedOutcome(t, store, root, "child"); child.Status != wantAgent || outcome == nil || outcome.Status != wantTurn { + t.Fatalf("child status = %q, outcome = %+v; want %q, %q", child.Status, outcome, wantAgent, wantTurn) + } + + turnID, err := store.StartRootMailboxTurn(t.Context(), root, agent) + if err != nil { + t.Fatal(err) + } + err = store.CommitRootTurn(t.Context(), RootTurnCommit{RootID: root, AgentID: agent, TurnID: turnID, Status: test.status}) + // Root commits alone retain the existing empty-status success default. + wantRootTurn := "running" + if test.terminal || test.status == "" { + if err != nil { + t.Fatal(err) + } + wantRootTurn = test.status + if wantRootTurn == "" { + wantRootTurn = "succeeded" + } + } else if want := fmt.Sprintf("invalid root turn status %q", test.status); err == nil || err.Error() != want { + t.Fatalf("root turn error = %v; want %q", err, want) + } + if outcome := savedOutcome(t, store, root, agent); outcome == nil || outcome.Status != wantRootTurn { + t.Fatalf("root outcome = %+v; want %q", outcome, wantRootTurn) + } + }) + } +} + +// Admission uses Go predicates while subscription discovery and root shutdown +// use SQL predicates. They must agree without treating unknown values as terminal. +func TestAgentStatusAdmissionAndSQLBoundariesAgree(t *testing.T) { + for _, test := range []struct { + status string + terminal bool + }{ + {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, + {"stopped", true}, {"deleted", true}, + {"queued", false}, {"running", false}, {"waiting", false}, {"idle", false}, + {"unknown", false}, {"", false}, {"Failed", false}, {" failed", false}, + } { + t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { + store, root, agent := newSwarmFixture(t) + if _, err := store.CreateBlackboardSubscription(t.Context(), root, agent, "key"); err != nil { + t.Fatal(err) + } + exec(t, store, `UPDATE agents SET status=? WHERE id=?`, test.status, agent) + subscribers, err := store.SubscribedAgents(t.Context(), root, "key") + if err != nil { + t.Fatal(err) + } + if test.terminal && len(subscribers) != 0 || !test.terminal && (len(subscribers) != 1 || subscribers[0] != agent) { + t.Fatalf("subscribers = %v for terminal=%v", subscribers, test.terminal) + } + _, err = store.EnqueueInbox(t.Context(), InboxEnqueue{RootID: root, AgentID: agent, Kind: "submit", Payload: RuntimePayload{Data: []byte("work")}}) + if test.terminal && !errors.Is(err, ErrRootTerminal) || !test.terminal && err != nil { + t.Fatalf("enqueue error = %v for terminal=%v", err, test.terminal) + } + _, err = store.EnsureAuthority(t.Context(), root) + if test.terminal && !errors.Is(err, ErrRootTerminal) || !test.terminal && err != nil { + t.Fatalf("authority error = %v for terminal=%v", err, test.terminal) + } + for _, operation := range []string{"stop", "fail"} { + exec(t, store, `UPDATE agents SET status=? WHERE id=?`, test.status, agent) + if operation == "stop" { + _, err = store.StopRoot(t.Context(), root, "test") + } else { + _, err = store.FailRoot(t.Context(), root, "test") + } + if test.terminal && !errors.Is(err, ErrRootTerminal) || !test.terminal && err != nil { + t.Fatalf("%s error = %v for terminal=%v", operation, err, test.terminal) + } + } + }) + } +} diff --git a/internal/session/turn_outcome.go b/internal/session/turn_outcome.go index 19050aa6d..588328f39 100644 --- a/internal/session/turn_outcome.go +++ b/internal/session/turn_outcome.go @@ -33,6 +33,17 @@ type TurnOutcome struct { LastActivityAt string `json:"last_activity_at,omitempty"` } +// IsTerminalTurnStatus reports whether status is a completed turn outcome. +// Completing a turn does not terminate its retained agent. +func IsTerminalTurnStatus(status string) bool { + switch status { + case "succeeded", "failed", "cancelled", "interrupted": + return true + default: + return false + } +} + // Scan decodes the nullable JSON projection using database/sql's pointer scan. func (outcome *TurnOutcome) Scan(value any) error { switch data := value.(type) { @@ -54,10 +65,11 @@ func turnEventStatus(kind string) string { if !strings.HasPrefix(kind, "turn.") && !strings.HasPrefix(kind, "agent.turn.") { return "" } - switch status := kind[strings.LastIndexByte(kind, '.')+1:]; status { - case "started": + status := kind[strings.LastIndexByte(kind, '.')+1:] + switch { + case status == "started": return "running" - case "succeeded", "failed", "cancelled", "interrupted": + case IsTerminalTurnStatus(status): return status default: return "" From 1bb0b4661fa4f7a0236dfdb9f377656c10f4e05d Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Wed, 30 Sep 2026 11:36:08 -0700 Subject: [PATCH 57/67] test: conform contract guards to repository lint rules --- internal/client/root_client_test.go | 17 +++++++++--- internal/mcp/config_contract_test.go | 3 +-- internal/session/runtime_status_test.go | 36 +++++++++++++++++++------ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/internal/client/root_client_test.go b/internal/client/root_client_test.go index e8c94a25d..69d403f4b 100644 --- a/internal/client/root_client_test.go +++ b/internal/client/root_client_test.go @@ -28,10 +28,19 @@ func TestRootClientCancellationTargetsPreserveStatusBoundaries(t *testing.T) { status string terminal bool }{ - {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, - {"queued", false}, {"running", false}, {"waiting", false}, - {"stopped", false}, {"deleted", false}, {"unknown", false}, - {"", false}, {"Succeeded", false}, {" succeeded", false}, + {"succeeded", true}, + {"failed", true}, + {"cancelled", true}, + {"interrupted", true}, + {"queued", false}, + {"running", false}, + {"waiting", false}, + {"stopped", false}, + {"deleted", false}, + {"unknown", false}, + {"", false}, + {"Succeeded", false}, + {" succeeded", false}, } { t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { connection := &statusRootConnection{staticRootConnection: newStaticRootConnection(), status: test.status} diff --git a/internal/mcp/config_contract_test.go b/internal/mcp/config_contract_test.go index 2a0b86071..f19bc4522 100644 --- a/internal/mcp/config_contract_test.go +++ b/internal/mcp/config_contract_test.go @@ -17,8 +17,7 @@ func TestMCPConfigContractParity(t *testing.T) { if savedType.NumField()+1 != runtimeType.NumField() || wireType.NumField() != runtimeType.NumField() { t.Fatal("MCP config shapes differ beyond runtime-only trust") } - for i := range runtimeType.NumField() { - field := runtimeType.Field(i) + for field := range runtimeType.Fields() { wire, ok := wireType.FieldByName(field.Name) wantTag := field.Tag switch field.Name { diff --git a/internal/session/runtime_status_test.go b/internal/session/runtime_status_test.go index 2d78bb4ff..c0210021f 100644 --- a/internal/session/runtime_status_test.go +++ b/internal/session/runtime_status_test.go @@ -11,10 +11,20 @@ func TestTurnAndCommandOutcomeStatusBoundaries(t *testing.T) { status string terminal bool }{ - {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, - {"queued", false}, {"running", false}, {"waiting", false}, {"idle", false}, - {"stopped", false}, {"deleted", false}, {"unknown", false}, - {"", false}, {"Succeeded", false}, {" succeeded", false}, + {"succeeded", true}, + {"failed", true}, + {"cancelled", true}, + {"interrupted", true}, + {"queued", false}, + {"running", false}, + {"waiting", false}, + {"idle", false}, + {"stopped", false}, + {"deleted", false}, + {"unknown", false}, + {"", false}, + {"Succeeded", false}, + {" succeeded", false}, } { t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { store, root, agent := newSwarmFixture(t) @@ -97,10 +107,20 @@ func TestAgentStatusAdmissionAndSQLBoundariesAgree(t *testing.T) { status string terminal bool }{ - {"succeeded", true}, {"failed", true}, {"cancelled", true}, {"interrupted", true}, - {"stopped", true}, {"deleted", true}, - {"queued", false}, {"running", false}, {"waiting", false}, {"idle", false}, - {"unknown", false}, {"", false}, {"Failed", false}, {" failed", false}, + {"succeeded", true}, + {"failed", true}, + {"cancelled", true}, + {"interrupted", true}, + {"stopped", true}, + {"deleted", true}, + {"queued", false}, + {"running", false}, + {"waiting", false}, + {"idle", false}, + {"unknown", false}, + {"", false}, + {"Failed", false}, + {" failed", false}, } { t.Run(fmt.Sprintf("status=%q", test.status), func(t *testing.T) { store, root, agent := newSwarmFixture(t) From 210f9755a1138040ad104a437dd94f03f1890e80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 19:00:56 +0000 Subject: [PATCH 58/67] chore(deps): bump the actions group across 1 directory with 6 updates Bumps the actions group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/setup-node](https://github.com/actions/setup-node) | `7.0.0` | `7.1.0` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.1` | `7.0.2` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `8.0.1` | `8.0.2` | | [github/codeql-action/init](https://github.com/github/codeql-action) | `4.37.9` | `4.38.3` | | [github/codeql-action/autobuild](https://github.com/github/codeql-action) | `4.37.9` | `4.38.3` | | [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.37.9` | `4.38.3` | Updates `actions/setup-node` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v7...v7.1.0) Updates `actions/upload-artifact` from 7.0.1 to 7.0.2 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/043fb46d1a93c77aae656e7c1c64a875d1fc6a0a...cf430e030ddbb5b0abf93d22962f4752f3646cd9) Updates `actions/download-artifact` from 8.0.1 to 8.0.2 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c...9000827ccba6bdab643e8b6fd33ac0654aef8333) Updates `github/codeql-action/init` from 4.37.9 to 4.38.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...24c54180a607b1449ed407dd24f251e4e9147c8d) Updates `github/codeql-action/autobuild` from 4.37.9 to 4.38.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...24c54180a607b1449ed407dd24f251e4e9147c8d) Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...24c54180a607b1449ed407dd24f251e4e9147c8d) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: actions/upload-artifact dependency-version: 7.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/download-artifact dependency-version: 8.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: github/codeql-action/init dependency-version: 4.38.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: github/codeql-action/autobuild dependency-version: 4.38.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: github/codeql-action/analyze dependency-version: 4.38.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] <support@github.com> --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/desktop-check.yml | 6 +++--- .github/workflows/desktop-release.yml | 8 ++++---- .github/workflows/docs-deploy.yml | 10 +++++----- .github/workflows/mobile.yml | 2 +- .github/workflows/publish-cli.yml | 28 +++++++++++++-------------- .github/workflows/security.yml | 6 +++--- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 691c66848..c86c326c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,7 +192,7 @@ jobs: with: go-version-file: go.mod cache: true - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: 24 cache: npm @@ -222,7 +222,7 @@ jobs: - run: node apps/web/scripts/performance.mjs - run: npm run test:example - name: Shared verified renderer for desktop and release consumers - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: ci-renderer if-no-files-found: error @@ -231,7 +231,7 @@ jobs: apps/web/renderer-manifest.json - name: Browser acceptance evidence if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: web-browser-evidence if-no-files-found: ignore @@ -246,7 +246,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.sha }} - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm @@ -261,7 +261,7 @@ jobs: - run: npm run test:docs:browser - run: npm run build:storybook:docs - name: Static docs artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: docs-static if-no-files-found: error @@ -343,14 +343,14 @@ jobs: with: go-version-file: go.mod cache: true - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: ci-renderer path: apps/web diff --git a/.github/workflows/desktop-check.yml b/.github/workflows/desktop-check.yml index 5ff360497..f13fb1589 100644 --- a/.github/workflows/desktop-check.yml +++ b/.github/workflows/desktop-check.yml @@ -19,7 +19,7 @@ jobs: with: go-version-file: go.mod cache: true - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm @@ -28,7 +28,7 @@ jobs: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' - run: node node_modules/electron/install.js - run: npx playwright install ffmpeg - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: ${{ inputs.renderer-artifact }} path: apps/web @@ -53,7 +53,7 @@ jobs: run: node apps/desktop/scripts/smoke.mjs - name: Desktop package and lifecycle evidence if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: desktop-ci-evidence if-no-files-found: warn diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index d52bfea2e..3a89ea644 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -45,7 +45,7 @@ jobs: with: go-version-file: go.mod cache: true - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm @@ -64,7 +64,7 @@ jobs: env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' - run: node node_modules/electron/install.js - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: ${{ inputs.renderer-artifact }} path: apps/web @@ -102,7 +102,7 @@ jobs: if (!(await stat(`${root}/${name}`)).size) throw new Error(`Missing final ${name}`); } NODE - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: desktop-release-arm64 path: apps/desktop/out/release @@ -111,7 +111,7 @@ jobs: compression-level: 0 - name: Sanitized startup diagnostics (including failures) if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: desktop-startup-diagnostics-arm64 path: apps/desktop/out/diagnostics/startup.json diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 3601f53d5..2f94e747a 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -25,7 +25,7 @@ jobs: with: ref: ${{ github.sha }} persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm @@ -51,7 +51,7 @@ jobs: npm run build:docs (cd apps/docs && node scripts/package-deploy.mjs) node apps/docs/scripts/worker-test.mjs - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: docs-deploy-${{ github.sha }} path: apps/docs/dist/deploy @@ -72,10 +72,10 @@ jobs: with: ref: ${{ github.sha }} persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: docs-deploy-${{ github.sha }} path: apps/docs/dist/deploy @@ -114,7 +114,7 @@ jobs: with: ref: ${{ github.sha }} persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml index 7c48f8282..8976a851d 100644 --- a/.github/workflows/mobile.yml +++ b/.github/workflows/mobile.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v7 with: ref: ${{ github.sha }} - - uses: actions/setup-node@v7 + - uses: actions/setup-node@v7.1.0 with: node-version: 24 cache: npm diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index f647c5331..0aede03fa 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -122,12 +122,12 @@ jobs: with: go-version-file: go.mod cache: true - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm - run: npm ci - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: ci-renderer path: apps/web @@ -150,7 +150,7 @@ jobs: -o "dist/release/$ASSET" ./cmd/whip - name: Accept the packaged binary from a fresh home with the tested renderer run: python3 scripts/test-distributions.py --binary "dist/release/$ASSET" --version "$RELEASE_TAG" - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: whipcode-bin-${{ matrix.goos }}-${{ matrix.goarch }} path: dist/release/${{ matrix.asset }} @@ -178,14 +178,14 @@ jobs: with: ref: ${{ needs.metadata.outputs.source }} persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: ci-renderer path: apps/web - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: whipcode-bin-linux-amd64 path: linux @@ -193,7 +193,7 @@ jobs: run: | chmod +x linux/whipcode-linux-x64 node apps/desktop/scripts/linux-smoke.mjs linux/whipcode-linux-x64 - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: release-linux-evidence path: linux/linux-runtime.json @@ -214,19 +214,19 @@ jobs: with: ref: ${{ needs.metadata.outputs.source }} persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: pattern: whipcode-bin-* path: candidate merge-multiple: true - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: desktop-release-arm64 path: candidate - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: release-linux-evidence path: candidate @@ -242,7 +242,7 @@ jobs: uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4 with: subject-path: candidate/* - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: release-candidate path: candidate @@ -278,14 +278,14 @@ jobs: ref: ${{ needs.metadata.outputs.source }} fetch-depth: 0 persist-credentials: false - - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' cache: npm - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: release-candidate path: candidate diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index bc64804d4..e3bafa1c2 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -56,11 +56,11 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.sha }} - - uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 + - uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4 with: languages: go queries: security-and-quality - - uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 - - uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4 + - uses: github/codeql-action/autobuild@24c54180a607b1449ed407dd24f251e4e9147c8d # v4 + - uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4 with: category: "/language:go" From 71f23a3118aae9f921bd8475916d94adc33dea75 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 17:41:09 -0700 Subject: [PATCH 59/67] fix(deps): repair security blockers for backend reorganization --- .github/workflows/ci.yml | 2 +- apps/docs/package.json | 2 +- docs/dependency-security.md | 58 +++ go.mod | 2 +- package-lock.json | 762 +++++++++++++++++++++++------- package.json | 5 + scripts/audit-production.mjs | 143 ++++++ scripts/audit-production.test.mjs | 115 +++++ 8 files changed, 910 insertions(+), 179 deletions(-) create mode 100644 docs/dependency-security.md create mode 100644 scripts/audit-production.mjs create mode 100644 scripts/audit-production.test.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e309f212b..cef88c125 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -205,7 +205,7 @@ jobs: run: | npm run generate npm run build - - run: npm audit --omit=dev --audit-level=high + - run: npm run audit:production - run: npm run check - name: Web application and component checks run: | diff --git a/apps/docs/package.json b/apps/docs/package.json index fa2acd73f..913125af9 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -24,7 +24,7 @@ "@base-ui/react": "1.8.0", "@stylexjs/stylex": "0.19.0", "@tanstack/react-router": "1.170.32", - "@tanstack/react-start": "1.168.49", + "@tanstack/react-start": "1.168.60", "react": "19.2.8", "react-dom": "19.2.8" }, diff --git a/docs/dependency-security.md b/docs/dependency-security.md new file mode 100644 index 000000000..0d15f8097 --- /dev/null +++ b/docs/dependency-security.md @@ -0,0 +1,58 @@ +# Dependency security repairs for the backend reorganization + +The October 16, 2026 rerun of #320 and #321 found vulnerabilities in the pinned +Go toolchain and npm dependency tree. These repairs are separate from the +behavior-preserving reorganization. SDK/protocol sources and database migrations +remain unchanged. + +- Go 1.27.2 replaces 1.27.0. The refreshed `govulncheck` reports no reachable + vulnerabilities; findings in unused dependency code remain visible. +- TanStack Start 1.168.60 applies the same targeted version update proposed by + [#328](https://github.com/context-labs/whip/pull/328). +- The existing compatible ranges resolve patched `compression`, `shell-quote`, + and `source-map-js` releases in the root lockfile. + +Two packages have no patched npm release. Root overrides temporarily pin reviewed +source archives from **pending, unmerged upstream PRs**: + +| Package | Upstream fix | Immutable revision | +| --- | --- | --- | +| braces | [Bound parser and AST depth](https://github.com/micromatch/braces/pull/88) | `a795ee83ecd011131b2d618fe754ac5a8e124dae` | +| node-forge | [Validate nested DigestAlgorithm length](https://github.com/digitalbazaar/forge/pull/1152) | `ceba34402e329f0365134f23fe19898756527d65` | + +These archives are fetched from the upstream repositories and recorded with +SHA-512 integrity in `package-lock.json`. They are not published registry +releases or floating branches. The braces archive includes unreleased upstream +parser fixes as well as the depth fix, so product/build suites must pass before +landing this repair. + +## Verification and audit behavior + +Run `npm run audit:production`. It first runs security regression tests and then +the existing `npm audit --omit=dev --audit-level=high` scan. + +The pinned braces archive still identifies itself as 3.0.3. npm consequently +reports [GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm) +even though its source is fixed. The audit script recognizes only that exact +advisory revision after checking the override, lockfile origin and integrity, +absence of duplicate package copies, installed version and patched-file hashes. +It reports the finding as verified patched; it does not call the raw audit clean. +Its transitive dependents inherit that disposition only through the reported +advisory graph. Other high/critical advisories, revised advisory metadata, +unexpected dependency copies, missing patches, malformed reports and audit +service failures still fail the gate. Moderate findings remain visible at the +existing high-severity threshold. + +Tests exercise deep/cyclic brace patterns and ASTs, ordinary brace expansion, +valid RSA signatures, malformed nested RSA DigestInfo, unknown advisories, +registry fallback and patch tampering. The SDK job runs this gate before the +existing frontend and SDK acceptance checks. + +## Returning to registry releases + +When upstream publishes fixes, review the release against these patches, remove +the corresponding override and regenerate the lockfile. Remove the associated +pin verification and, for braces, its single-advisory disposition at the same +time. Retain the behavioral security regressions. Run the audit and affected +product/build suites; do not change a version or archive merely to suppress an +advisory. diff --git a/go.mod b/go.mod index 22a794172..d1024bd75 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/context-labs/whip -go 1.27.0 +go 1.27.2 require ( charm.land/bubbles/v2 v2.2.1 diff --git a/package-lock.json b/package-lock.json index 2caae1479..f7d14f7ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,7 +64,7 @@ "@base-ui/react": "1.8.0", "@stylexjs/stylex": "0.19.0", "@tanstack/react-router": "1.170.32", - "@tanstack/react-start": "1.168.49", + "@tanstack/react-start": "1.168.60", "react": "19.2.8", "react-dom": "19.2.8" }, @@ -4048,38 +4048,6 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, - "node_modules/@expo/metro/node_modules/metro-config": { - "version": "0.84.5", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.84.5.tgz", - "integrity": "sha512-zie+uN6oohscowi2S7ByU+wUw6CrT4ZxW9uAbONOObSxx86RGmnIAmjXHLkfmcdYoY7jzOPEbqcI6oeVmqyBQA==", - "license": "MIT", - "dependencies": { - "connect": "^3.6.5", - "flow-enums-runtime": "^0.0.6", - "jest-validate": "^29.7.0", - "metro": "0.84.5", - "metro-cache": "0.84.5", - "metro-core": "0.84.5", - "metro-runtime": "0.84.5", - "yaml": "^2.6.1" - }, - "engines": { - "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" - } - }, - "node_modules/@expo/metro/node_modules/metro-runtime": { - "version": "0.84.5", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.84.5.tgz", - "integrity": "sha512-U1m2+d1Pr+JO2/iVXBB2OfXXityz7tqwIorxfrT15IEgaHvpJBq/OHiqnOWPKJbUl3JcxjcdviZZOKk85oK4Qg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.25.0", - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" - } - }, "node_modules/@expo/osascript": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.7.1.tgz", @@ -8507,19 +8475,19 @@ } }, "node_modules/@tanstack/react-start": { - "version": "1.168.49", - "resolved": "https://registry.npmjs.org/@tanstack/react-start/-/react-start-1.168.49.tgz", - "integrity": "sha512-iQb1ZoEHqvZMGLR4G7v3tTtgL06yv/bwxvGP3waVHxVn7bRpyopM44YbOluaGkcJzc13ZTvdLKWYNAN3bxMX/Q==", - "license": "MIT", - "dependencies": { - "@tanstack/react-router": "1.170.32", - "@tanstack/react-start-client": "1.168.30", - "@tanstack/react-start-rsc": "0.1.48", - "@tanstack/react-start-server": "1.167.37", - "@tanstack/router-utils": "1.162.2", - "@tanstack/start-client-core": "1.170.27", - "@tanstack/start-plugin-core": "1.171.39", - "@tanstack/start-server-core": "1.169.31", + "version": "1.168.60", + "resolved": "https://registry.npmjs.org/@tanstack/react-start/-/react-start-1.168.60.tgz", + "integrity": "sha512-WMOM0Xlh2lPbVlbjYM6uOxOpiaWRPvODm/dwkLsGKq5tjyHOHZmKckJgwlrZl7OQUqFlOZHYj8bKUTgoeg8cUQ==", + "license": "MIT", + "dependencies": { + "@tanstack/react-router": "1.170.41", + "@tanstack/react-start-client": "1.168.39", + "@tanstack/react-start-rsc": "0.1.59", + "@tanstack/react-start-server": "1.167.46", + "@tanstack/router-utils": "1.162.3", + "@tanstack/start-client-core": "1.170.34", + "@tanstack/start-plugin-core": "1.171.49", + "@tanstack/start-server-core": "1.169.39", "pathe": "^2.0.3" }, "engines": { @@ -8548,14 +8516,14 @@ } }, "node_modules/@tanstack/react-start-client": { - "version": "1.168.30", - "resolved": "https://registry.npmjs.org/@tanstack/react-start-client/-/react-start-client-1.168.30.tgz", - "integrity": "sha512-qsZuykUl1EF0/rc1bin1RtjFzz07YMOTBzhOstSDzbOVm/WKf1QKFTN+qAZi74xlbXSWNuT2MiFRyg4RKwj8iw==", + "version": "1.168.39", + "resolved": "https://registry.npmjs.org/@tanstack/react-start-client/-/react-start-client-1.168.39.tgz", + "integrity": "sha512-Uby0uo37JlQgUKHU0snDwH9nYiEeAjm9+7pUOFgycU/UszEILC2SO2DSCoNnCMuHKj9z+4URKzBYIP2exT9+wg==", "license": "MIT", "dependencies": { - "@tanstack/react-router": "1.170.32", - "@tanstack/router-core": "1.171.27", - "@tanstack/start-client-core": "1.170.27" + "@tanstack/react-router": "1.170.41", + "@tanstack/router-core": "1.171.34", + "@tanstack/start-client-core": "1.170.34" }, "engines": { "node": ">=22.12.0" @@ -8569,15 +8537,70 @@ "react-dom": ">=18.0.0 || >=19.0.0" } }, + "node_modules/@tanstack/react-start-client/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-start-client/node_modules/@tanstack/react-router": { + "version": "1.170.41", + "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.170.41.tgz", + "integrity": "sha512-Mpvw8Wm5MGDbTqI8Yc9flLKxbOHwoWocv0H2aGKcgw2a017oK5nZWqa954P+DrUx/8fI98YNywnHP5XcD3tQ9w==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "@tanstack/react-store": "^0.11.2", + "@tanstack/router-core": "1.171.34", + "isbot": "^5.1.22" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-start-client/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/react-start-server": { - "version": "1.167.37", - "resolved": "https://registry.npmjs.org/@tanstack/react-start-server/-/react-start-server-1.167.37.tgz", - "integrity": "sha512-cODHpFU8vIm7AdHii9W3NEuwyruNmT5wLDZjRsJLT9Jp+7FACnfJrRbvxnp1ldSv/9mxcHKi/OgwbdHQeMZcAQ==", + "version": "1.167.46", + "resolved": "https://registry.npmjs.org/@tanstack/react-start-server/-/react-start-server-1.167.46.tgz", + "integrity": "sha512-K7z8xBOEdp8u5CZCxWrbS0tFtk5XZGMdhssLeZlRZKlLDbX7BKLdMtJ7th5sR6QVt9MTUAg3LcoqvJMPSFF+lg==", "license": "MIT", "dependencies": { - "@tanstack/react-router": "1.170.32", - "@tanstack/router-core": "1.171.27", - "@tanstack/start-server-core": "1.169.31" + "@tanstack/react-router": "1.170.41", + "@tanstack/router-core": "1.171.34", + "@tanstack/start-server-core": "1.169.39" }, "engines": { "node": ">=22.12.0" @@ -8591,19 +8614,110 @@ "react-dom": ">=18.0.0 || >=19.0.0" } }, + "node_modules/@tanstack/react-start-server/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-start-server/node_modules/@tanstack/react-router": { + "version": "1.170.41", + "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.170.41.tgz", + "integrity": "sha512-Mpvw8Wm5MGDbTqI8Yc9flLKxbOHwoWocv0H2aGKcgw2a017oK5nZWqa954P+DrUx/8fI98YNywnHP5XcD3tQ9w==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "@tanstack/react-store": "^0.11.2", + "@tanstack/router-core": "1.171.34", + "isbot": "^5.1.22" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-start-server/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-start/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-start/node_modules/@tanstack/react-router": { + "version": "1.170.41", + "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.170.41.tgz", + "integrity": "sha512-Mpvw8Wm5MGDbTqI8Yc9flLKxbOHwoWocv0H2aGKcgw2a017oK5nZWqa954P+DrUx/8fI98YNywnHP5XcD3tQ9w==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "@tanstack/react-store": "^0.11.2", + "@tanstack/router-core": "1.171.34", + "isbot": "^5.1.22" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, "node_modules/@tanstack/react-start/node_modules/@tanstack/react-start-rsc": { - "version": "0.1.48", - "resolved": "https://registry.npmjs.org/@tanstack/react-start-rsc/-/react-start-rsc-0.1.48.tgz", - "integrity": "sha512-UglRdTMuF3c4dvzL/gh4dMVbMWHsPy8ZgTQdT2qpTlyt1b/3m+R40tBFdsfTgw76VTXivW+qV/ih0PN9000XTw==", + "version": "0.1.59", + "resolved": "https://registry.npmjs.org/@tanstack/react-start-rsc/-/react-start-rsc-0.1.59.tgz", + "integrity": "sha512-M2Lqxkk5C1zQncQs5paqX+/OLdOht51pg6D84YfLMrNsjhU/nzb6wd92MIja0mi5i23+L+fxLLjQYR2DObjBlw==", "license": "MIT", "dependencies": { - "@tanstack/react-router": "1.170.32", - "@tanstack/router-core": "1.171.27", - "@tanstack/router-utils": "1.162.2", - "@tanstack/start-client-core": "1.170.27", + "@tanstack/react-router": "1.170.41", + "@tanstack/router-core": "1.171.34", + "@tanstack/router-utils": "1.162.3", + "@tanstack/start-client-core": "1.170.34", "@tanstack/start-fn-stubs": "1.162.0", - "@tanstack/start-plugin-core": "1.171.39", - "@tanstack/start-storage-context": "1.167.29", + "@tanstack/start-plugin-core": "1.171.49", + "@tanstack/start-storage-context": "1.167.36", "pathe": "^2.0.3" }, "engines": { @@ -8632,13 +8746,55 @@ } } }, + "node_modules/@tanstack/react-start/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-start/node_modules/@tanstack/router-utils": { + "version": "1.162.3", + "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.162.3.tgz", + "integrity": "sha512-Icb0xGuG1+54IV0WMLRcc3ErTx2HeJWyPG661FkQ8UT6guoBq1FJjFRqlG/JS0xi4mFFkBhvwO7tbLa32f3yxA==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.29.8", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "ansis": "^4.3.1", + "babel-dead-code-elimination": "^1.0.12", + "diff": "^8.0.4", + "pathe": "^2.0.3", + "tinyglobby": "^0.2.17" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/react-store": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.11.1.tgz", - "integrity": "sha512-HaIGKI3YLmjBYIvy5DFDY23oNaYZIsTZfngey07Uh5iLVJgM3bIGCnZeOFOqzjFld9JHWcaHJnasD/bKoGKwJQ==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.11.2.tgz", + "integrity": "sha512-oj5O5DmiMWE+ih+SioX2ayC1kbK7d3fpLx0B75fPJr9nY3zU+hoW010yr64qXsY/9fyiLVE2bn5mGNV3owm8RQ==", "license": "MIT", "dependencies": { - "@tanstack/store": "0.11.1", + "@tanstack/store": "0.11.2", "use-sync-external-store": "^1.6.0" }, "funding": { @@ -8690,6 +8846,7 @@ "version": "1.167.33", "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.167.33.tgz", "integrity": "sha512-Z3lCWIPuRUMPmuI8Mm48x/s49TxmHOaFVZ52j1W1QKYrsFHyT6U/h9bqfHJDxfQ8kz7y9q+W1YPKZ15Ee7yuCA==", + "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.5", @@ -8713,6 +8870,7 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -8722,6 +8880,7 @@ "version": "1.168.35", "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.168.35.tgz", "integrity": "sha512-foDAZKFqHXae+oFbIgcsSvy2QCVRn7XdS3nhwcRvD+ed6JrKPUP/1lQMsZLJqWycgR1vkZF7gs955KGa0NZQ0w==", + "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.28.5", @@ -8770,6 +8929,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.3.0.tgz", "integrity": "sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", @@ -8824,6 +8984,7 @@ "version": "1.162.2", "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.162.2.tgz", "integrity": "sha512-hTWqJtqIFFdvuCl8WXNyrodp2L9zo2G37xKRrcVmVRWpAB2h+U1LuRAfS4tsFTiWOIoE/B+WDVFB8JpoEdw6jQ==", + "dev": true, "license": "MIT", "dependencies": { "@babel/generator": "^7.28.5", @@ -8844,15 +9005,15 @@ } }, "node_modules/@tanstack/start-client-core": { - "version": "1.170.27", - "resolved": "https://registry.npmjs.org/@tanstack/start-client-core/-/start-client-core-1.170.27.tgz", - "integrity": "sha512-Ro6ZSM0NgYKDMxM0e8qyU4mBfnld2Zb74BA/9f4i35C0Y3IAA8Zxs/DIPfOo9VRYWp5c5n5Q8dRBn2qn0vtPhQ==", + "version": "1.170.34", + "resolved": "https://registry.npmjs.org/@tanstack/start-client-core/-/start-client-core-1.170.34.tgz", + "integrity": "sha512-LfwZSbau2MLLZ/uPAoO+NC9fK3J66c0wLhnNQqIa+Goqw7bXPjkHwlsjY7evlUz1AnyhhQ1Qab95v+VmP0TZ9A==", "license": "MIT", "dependencies": { - "@tanstack/router-core": "1.171.27", + "@tanstack/router-core": "1.171.34", "@tanstack/start-fn-stubs": "1.162.0", - "@tanstack/start-storage-context": "1.167.29", - "seroval": "^1.6.2" + "@tanstack/start-storage-context": "1.167.36", + "seroval": "^1.6.7" }, "engines": { "node": ">=22.12.0" @@ -8862,6 +9023,38 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/start-client-core/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-client-core/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/start-fn-stubs": { "version": "1.162.0", "resolved": "https://registry.npmjs.org/@tanstack/start-fn-stubs/-/start-fn-stubs-1.162.0.tgz", @@ -8876,31 +9069,32 @@ } }, "node_modules/@tanstack/start-plugin-core": { - "version": "1.171.39", - "resolved": "https://registry.npmjs.org/@tanstack/start-plugin-core/-/start-plugin-core-1.171.39.tgz", - "integrity": "sha512-Zyj6G4MDFLXcHYhPavhewCBo8dsxi3qvPk31zl/QtTzYzOY9rJHDDBGarKsJq20ziChmkGn/sttYqb4vGCxJDA==", + "version": "1.171.49", + "resolved": "https://registry.npmjs.org/@tanstack/start-plugin-core/-/start-plugin-core-1.171.49.tgz", + "integrity": "sha512-HPOb7LnMc71k38cd5uvMybPPUU/Q/56KvSqQzSWz7cps1ZDFXaxUM6EFaFHLCdgTWqGexNGDdRE+sUVPVBM4Xg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "7.27.1", - "@babel/core": "^7.28.5", - "@babel/types": "^7.28.5", - "@tanstack/router-core": "1.171.27", - "@tanstack/router-generator": "1.167.33", - "@tanstack/router-plugin": "1.168.35", - "@tanstack/router-utils": "1.162.2", - "@tanstack/start-server-core": "1.169.31", - "exsolve": "^1.0.7", - "lightningcss": "^1.32.0", + "@babel/code-frame": "7.29.7", + "@babel/core": "^7.29.7", + "@babel/types": "^7.29.8", + "@jridgewell/remapping": "^2.3.5", + "@tanstack/router-core": "1.171.34", + "@tanstack/router-generator": "1.167.40", + "@tanstack/router-plugin": "1.168.42", + "@tanstack/router-utils": "1.162.3", + "@tanstack/start-server-core": "1.169.39", + "exsolve": "^1.1.1", + "lightningcss": "^1.33.0", "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "seroval": "^1.6.2", + "picomatch": "^4.0.7", + "seroval": "^1.6.7", "source-map": "^0.7.6", - "srvx": "^0.11.9", - "tinyglobby": "^0.2.15", - "ufo": "^1.5.4", - "vitefu": "^1.1.1", + "srvx": "^0.11.22", + "tinyglobby": "^0.2.17", + "ufo": "^1.6.4", + "vitefu": "^1.1.3", "xmlbuilder2": "^4.0.3", - "zod": "^4.4.3" + "zod": "^4.5.4" }, "engines": { "node": ">=22.12.0" @@ -8922,18 +9116,139 @@ } } }, - "node_modules/@tanstack/start-plugin-core/node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "node_modules/@tanstack/start-plugin-core/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" }, "engines": { - "node": ">=6.9.0" + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-plugin-core/node_modules/@tanstack/router-core/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-plugin-core/node_modules/@tanstack/router-generator": { + "version": "1.167.40", + "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.167.40.tgz", + "integrity": "sha512-WkEueqEvsBBudzO0fx1nWfOmRNW8OAvBoVABTGls9bAWzjdC+KDGHvjCNrvn88ofs1F6gqL8aWnzKCbxW3dCyQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8", + "@tanstack/router-core": "1.171.34", + "@tanstack/router-utils": "1.162.3", + "@tanstack/virtual-file-routes": "1.162.0", + "jiti": "^2.7.0", + "magic-string": "^0.30.21", + "prettier": "^3.9.6", + "zod": "^4.5.4" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-plugin-core/node_modules/@tanstack/router-plugin": { + "version": "1.168.42", + "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.168.42.tgz", + "integrity": "sha512-vAR5WXJh/ErseEWQftDhsJcr2c++ucRQ6FbqN3ygMO44+ZxxRfW3sIpZmddHROVSmBk8jc6MrwjTPNjVhd62Vw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "@tanstack/router-core": "1.171.34", + "@tanstack/router-generator": "1.167.40", + "@tanstack/router-utils": "1.162.3", + "chokidar": "^5.0.0", + "unplugin": "^3.3.0", + "zod": "^4.5.4" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@rsbuild/core": ">=1.0.2 || ^2.0.0", + "@tanstack/react-router": "^1.170.41", + "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0 || >=8.0.0", + "vite-plugin-solid": "^2.11.10 || ^3.0.0-0", + "webpack": ">=5.92.0" + }, + "peerDependenciesMeta": { + "@rsbuild/core": { + "optional": true + }, + "@tanstack/react-router": { + "optional": true + }, + "vite": { + "optional": true + }, + "vite-plugin-solid": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@tanstack/start-plugin-core/node_modules/@tanstack/router-utils": { + "version": "1.162.3", + "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.162.3.tgz", + "integrity": "sha512-Icb0xGuG1+54IV0WMLRcc3ErTx2HeJWyPG661FkQ8UT6guoBq1FJjFRqlG/JS0xi4mFFkBhvwO7tbLa32f3yxA==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.29.8", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "ansis": "^4.3.1", + "babel-dead-code-elimination": "^1.0.12", + "diff": "^8.0.4", + "pathe": "^2.0.3", + "tinyglobby": "^0.2.17" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-plugin-core/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/@tanstack/start-plugin-core/node_modules/source-map": { @@ -8945,19 +9260,77 @@ "node": ">= 12" } }, + "node_modules/@tanstack/start-plugin-core/node_modules/unplugin": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.4.0.tgz", + "integrity": "sha512-9skdIFlCsPdFV7wUfZxNsFInlW+7nJmGu2gkTu0OUhF56aXGsHab9x52/QhdJ4lC7ZDPWTxbiC4ANqVlsuaW3w==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "picomatch": "^4.0.7", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@farmfe/core": "*", + "@rsbuild/core": "*", + "@rspack/core": "*", + "bun-types-no-globals": "*", + "esbuild": "*", + "rolldown": "*", + "rollup": "*", + "unloader": "*", + "vite": "*", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@farmfe/core": { + "optional": true + }, + "@rsbuild/core": { + "optional": true + }, + "@rspack/core": { + "optional": true + }, + "bun-types-no-globals": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "rolldown": { + "optional": true + }, + "rollup": { + "optional": true + }, + "unloader": { + "optional": true + }, + "vite": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, "node_modules/@tanstack/start-server-core": { - "version": "1.169.31", - "resolved": "https://registry.npmjs.org/@tanstack/start-server-core/-/start-server-core-1.169.31.tgz", - "integrity": "sha512-56w8l+Fao01YCrmv0hzNxL3b3FRmqLRGdE11izZNQsW+1CcSYuehAM5khWKABuI1DI/UIBLGV7BwL4Dlg0eHCw==", + "version": "1.169.39", + "resolved": "https://registry.npmjs.org/@tanstack/start-server-core/-/start-server-core-1.169.39.tgz", + "integrity": "sha512-pqqkxhXY46nuFSYt6TsMGyABiplUzHFHndKAlRRGC0fWDrJCH1koWxVMoxySa51ZETV79f/z73b5UZ1jfIkXwQ==", "license": "MIT", "dependencies": { - "@tanstack/history": "1.162.1", - "@tanstack/router-core": "1.171.27", - "@tanstack/start-client-core": "1.170.27", - "@tanstack/start-storage-context": "1.167.29", + "@tanstack/history": "1.162.4", + "@tanstack/router-core": "1.171.34", + "@tanstack/start-client-core": "1.170.34", + "@tanstack/start-storage-context": "1.167.36", "fetchdts": "^0.1.6", "h3-v2": "npm:h3@2.0.1-rc.20", - "seroval": "^1.6.2" + "seroval": "^1.6.7" }, "engines": { "node": ">=22.12.0" @@ -8967,13 +9340,45 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/start-server-core/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-server-core/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/start-storage-context": { - "version": "1.167.29", - "resolved": "https://registry.npmjs.org/@tanstack/start-storage-context/-/start-storage-context-1.167.29.tgz", - "integrity": "sha512-8qfprC5774XMRDQlMogkfiGpFLiBf0xDG4bMFUbfkSzpCAQwpLbgGY4Zwft22O9rKYq2vUXusKAdVjvJTUEquQ==", + "version": "1.167.36", + "resolved": "https://registry.npmjs.org/@tanstack/start-storage-context/-/start-storage-context-1.167.36.tgz", + "integrity": "sha512-x+xCXK2GtFzY6NbXqAg8YpU6cwAjDfMeYSNzxfGzntpjbwBRHHrXeC/kYUnBBQCV7wK4kJ8vBBQGP0OyYTasUg==", "license": "MIT", "dependencies": { - "@tanstack/router-core": "1.171.27" + "@tanstack/router-core": "1.171.34" }, "engines": { "node": ">=22.12.0" @@ -8983,10 +9388,42 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/start-storage-context/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/start-storage-context/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/store": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.11.1.tgz", - "integrity": "sha512-mzTOBhypOuDJAy/D8n2MfUZ1HFkXnmSETviRyhqEC8LUE7/IZQExOTxMANj3KjTofYTkFNpBY67qaVrT41YccA==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.11.2.tgz", + "integrity": "sha512-sJ4mjol8uQsHV0gOJzzjwXfh2Fwm+Sz0+8deqiTm4jGbMdjzNSW+xZCFm0kUa870uhd8yi+DpKnZb5Kc4apa0Q==", "license": "MIT", "funding": { "type": "github", @@ -10862,14 +11299,14 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "resolved": "https://codeload.github.com/micromatch/braces/tar.gz/a795ee83ecd011131b2d618fe754ac5a8e124dae", + "integrity": "sha512-w/zrxDVIuC1EaZHrMyq3LyFTCwQ/+badAhpR+FfC8Me0qBPxJ3zSWg5ux3fwZMjVyUUwM9H1tQU7Sj2pAwZuqA==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { - "node": ">=8" + "node": ">=8.3" } }, "node_modules/browserslist": { @@ -11791,14 +12228,15 @@ } }, "node_modules/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.2.tgz", + "integrity": "sha512-o8vI5RE5A6EVVOd9o41jKp41aJom+QTEO/Bx8MYNjexMo/Bv2WOjUfZr+aL0WnYSgymUy6zeguqLTsIhV0gMvQ==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", + "destroy": "1.2.0", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", @@ -11806,6 +12244,10 @@ }, "engines": { "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/compression/node_modules/debug": { @@ -13916,9 +14358,9 @@ "license": "Apache-2.0" }, "node_modules/exsolve": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.1.tgz", - "integrity": "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.3.tgz", + "integrity": "sha512-kuzL9zherLQoqDeQaS55AiiIg1kb4KYXaSusTtgZTPlvKP2gGCI82LNmBNh5RjDVUXIcmgx+/Mx7vPwRzBbhJA==", "license": "MIT" }, "node_modules/extend": { @@ -19033,38 +19475,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/metro/node_modules/metro-config": { - "version": "0.84.5", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.84.5.tgz", - "integrity": "sha512-zie+uN6oohscowi2S7ByU+wUw6CrT4ZxW9uAbONOObSxx86RGmnIAmjXHLkfmcdYoY7jzOPEbqcI6oeVmqyBQA==", - "license": "MIT", - "dependencies": { - "connect": "^3.6.5", - "flow-enums-runtime": "^0.0.6", - "jest-validate": "^29.7.0", - "metro": "0.84.5", - "metro-cache": "0.84.5", - "metro-core": "0.84.5", - "metro-runtime": "0.84.5", - "yaml": "^2.6.1" - }, - "engines": { - "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" - } - }, - "node_modules/metro/node_modules/metro-runtime": { - "version": "0.84.5", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.84.5.tgz", - "integrity": "sha512-U1m2+d1Pr+JO2/iVXBB2OfXXityz7tqwIorxfrT15IEgaHvpJBq/OHiqnOWPKJbUl3JcxjcdviZZOKk85oK4Qg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.25.0", - "flow-enums-runtime": "^0.0.6" - }, - "engines": { - "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" - } - }, "node_modules/metro/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", @@ -20527,9 +20937,9 @@ } }, "node_modules/node-forge": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", - "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "version": "1.4.1-0", + "resolved": "https://codeload.github.com/digitalbazaar/forge/tar.gz/ceba34402e329f0365134f23fe19898756527d65", + "integrity": "sha512-fYRFJf8ymZNJ5jGirbhuwAljM0rSJG03cldnAK3sJRMDHSS+tG8DPosOB8he34pGWMylVCMOtnIxUEepsME2Rg==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -23372,18 +23782,18 @@ } }, "node_modules/seroval": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.6.4.tgz", - "integrity": "sha512-LErWMNS2RRFdu2RMA5u/PA59/IWs0XsikyEXGQ2/36iEWFrdG0ABmg17E17cikrv76891kOAMq3TkTFXpwAHXw==", + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.6.9.tgz", + "integrity": "sha512-UeEzHwAK+yl0YLbsvROV1t5yMYEwZZ0CfKYxDvUgS2fO9Vxdf8djqVIB+OuVpuawRNPqw68LE1Du/GMsW2ZPqA==", "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/seroval-plugins": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.6.4.tgz", - "integrity": "sha512-R0f1U9hmn38+dFMz6b6ab8lwucmw4AtiY7St+JPWudy1dm+Bs3g884nyrsH9Cy6rKpZKLYayXuMda9GZ/fl8JQ==", + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.6.9.tgz", + "integrity": "sha512-kiDK/Tb8IWZ61WEU8pA2PDmAuw37gKph9Y77OZlD56mg0Y2g0Bg7gZ1HeHhs5d40w+nRoUq/wj08V26ilbez9g==", "license": "MIT", "engines": { "node": ">=10" @@ -23465,9 +23875,9 @@ } }, "node_modules/shell-quote": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", - "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.12.0.tgz", + "integrity": "sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -23649,9 +24059,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" diff --git a/package.json b/package.json index c6b1b4676..4e6f1fba6 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "apps/*" ], "scripts": { + "audit:production": "node --test scripts/audit-production.test.mjs && node scripts/audit-production.mjs", "generate": "npm run generate -w @whip/protocol", "build": "npm run build -w @whip/sdk", "check": "npm run check -w @whip/protocol && npm run check -w @whip/sdk && npm run build -w @whip/client-example", @@ -70,5 +71,9 @@ "vite": "8.2.2", "vitest": "5.0.0" }, + "overrides": { + "braces": "https://codeload.github.com/micromatch/braces/tar.gz/a795ee83ecd011131b2d618fe754ac5a8e124dae", + "node-forge": "https://codeload.github.com/digitalbazaar/forge/tar.gz/ceba34402e329f0365134f23fe19898756527d65" + }, "version": "0.0.0" } diff --git a/scripts/audit-production.mjs b/scripts/audit-production.mjs new file mode 100644 index 000000000..6187e0af2 --- /dev/null +++ b/scripts/audit-production.mjs @@ -0,0 +1,143 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import { readFileSync, realpathSync } from "node:fs"; +import { createRequire } from "node:module"; +import { dirname, join, resolve } from "node:path"; +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const blocking = new Set(["high", "critical"]); +const severities = new Set(["info", "low", "moderate", "high", "critical"]); + +// Pending upstream fixes, not registry releases. Keep these independent of the +// manifest so replacing an override cannot silently preserve the audit exception. +// Provenance and removal instructions: docs/dependency-security.md. +export const securityPins = { + braces: { + version: "3.0.3", + resolved: "https://codeload.github.com/micromatch/braces/tar.gz/a795ee83ecd011131b2d618fe754ac5a8e124dae", + integrity: "sha512-w/zrxDVIuC1EaZHrMyq3LyFTCwQ/+badAhpR+FfC8Me0qBPxJ3zSWg5ux3fwZMjVyUUwM9H1tQU7Sj2pAwZuqA==", + files: { + "index.js": "332ea07c7b006361aad12aa994ca75dc1db8e8382b884909e2f38f10b85c88a4", + "lib/assert-depth.js": "20642e4be21253e8269e42511d61f076fcac2903c27c94f7b1194f182d6b36dd", + "lib/compile.js": "0527119921a3117bfbb7a3a86d400bcaf26c3988628688301ee17c5cc0003719", + "lib/expand.js": "bdcde9b36e94d248c5035ab8f98f4a20189c973fa44ee68cd576ba7ebf28022b", + "lib/parse.js": "32702456744324649a1a29ae234e08eb392d3db53dd7a5c872de808bba03c6fb", + "lib/stringify.js": "056ab10d759e5d2ca81fc888b122acf450c692b5e409dc19a41aca06aba8f2ef", + }, + }, + "node-forge": { + version: "1.4.1-0", + resolved: "https://codeload.github.com/digitalbazaar/forge/tar.gz/ceba34402e329f0365134f23fe19898756527d65", + integrity: "sha512-fYRFJf8ymZNJ5jGirbhuwAljM0rSJG03cldnAK3sJRMDHSS+tG8DPosOB8he34pGWMylVCMOtnIxUEepsME2Rg==", + files: { + "lib/rsa.js": "acc22e5d36e27832c34e02dd3933aad7977d45b047eead5016520735efedc9c5", + }, + }, +}; + +export function verifySecurityPins(directory = root) { + directory = realpathSync(directory); + const manifest = JSON.parse(readFileSync(join(directory, "package.json"), "utf8")); + const lock = JSON.parse(readFileSync(join(directory, "package-lock.json"), "utf8")); + const require = createRequire(join(directory, "package.json")); + for (const [name, pin] of Object.entries(securityPins)) { + const location = `node_modules/${name}`; + const copies = Object.keys(lock.packages).filter((path) => + path === location || path.endsWith(`/${location}`)); + assert.deepEqual(copies, [location], `Unexpected copies of ${name}`); + assert.equal(manifest.overrides?.[name], pin.resolved, `${name} override changed`); + for (const field of ["version", "resolved", "integrity"]) { + assert.equal(lock.packages[location][field], pin[field], `${name} lock ${field} changed`); + } + const packageFile = join(directory, location, "package.json"); + assert.equal(require.resolve(`${name}/package.json`), packageFile); + assert.equal(JSON.parse(readFileSync(packageFile, "utf8")).version, pin.version); + for (const [file, expected] of Object.entries(pin.files)) { + const actual = createHash("sha256").update(readFileSync(join(directory, location, file))).digest("hex"); + assert.equal(actual, expected, `${name}/${file} does not contain the reviewed fix`); + } + } +} + +function isPatchedBracesFinding(finding) { + return finding.name === "braces" && finding.dependency === "braces" + && finding.source === 1240992 && finding.range === "<=3.0.3" + && finding.severity === "high" + && finding.url === "https://github.com/advisories/GHSA-vfj7-8cjw-p6xm"; +} + +export function classifyAudit(report) { + assert.equal(report.auditReportVersion, 2, "Unsupported npm audit report"); + assert.ok(!report.error, "npm audit reported an error"); + const vulnerabilities = report.vulnerabilities; + assert.ok(vulnerabilities && typeof vulnerabilities === "object" && !Array.isArray(vulnerabilities)); + for (const [name, entry] of Object.entries(vulnerabilities)) { + assert.equal(entry.name, name); + assert.ok(severities.has(entry.severity) && Array.isArray(entry.via), `Malformed finding: ${name}`); + for (const via of entry.via) { + if (typeof via === "string") { + assert.ok(Object.hasOwn(vulnerabilities, via), `Missing audit dependency: ${via}`); + } else { + assert.ok(via && typeof via.name === "string" && typeof via.url === "string" + && severities.has(via.severity), `Malformed advisory: ${name}`); + } + } + } + + const patched = new Map(); + const unresolved = new Map(); + for (const [name, entry] of Object.entries(vulnerabilities)) { + if (!blocking.has(entry.severity)) continue; + const pending = [name]; + const seen = new Set(); + let explained = false; + while (pending.length) { + const dependency = pending.pop(); + if (seen.has(dependency)) continue; + seen.add(dependency); + for (const via of vulnerabilities[dependency].via) { + if (typeof via === "string") { + pending.push(via); + } else if (blocking.has(via.severity)) { + explained = true; + const findings = isPatchedBracesFinding(via) ? patched : unresolved; + findings.set(`${via.name}:${via.url}`, via); + } + } + } + assert.ok(explained, `Unexplained blocking audit finding: ${name}`); + } + return { patched: [...patched.values()], unresolved: [...unresolved.values()] }; +} + +function main() { + verifySecurityPins(); + const result = spawnSync("npm", ["audit", "--omit=dev", "--audit-level=high", "--json"], { + cwd: root, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, + }); + if (result.error) throw result.error; + assert.ok(result.status === 0 || result.status === 1, result.stderr || "npm audit failed"); + const report = JSON.parse(result.stdout); + const findings = classifyAudit(report); + if (result.status === 1) { + assert.ok(findings.patched.length + findings.unresolved.length > 0, "Unexplained npm audit failure"); + } + for (const finding of findings.patched) { + console.log(`Verified patched upstream source: ${finding.name} ${finding.url}`); + } + for (const finding of findings.unresolved) { + console.error(`${finding.severity}: ${finding.name} — ${finding.url}`); + } + console.log(`Production audit: ${findings.unresolved.length} unremediated high/critical advisories; ${findings.patched.length} verified patched advisory.`); + console.log("Raw npm audit dependency counts:", JSON.stringify(report.metadata?.vulnerabilities)); + if (findings.unresolved.length) process.exitCode = 1; +} + +if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + try { main(); } catch (error) { + console.error(error.message); + process.exitCode = 1; + } +} diff --git a/scripts/audit-production.test.mjs b/scripts/audit-production.test.mjs new file mode 100644 index 000000000..a8715972d --- /dev/null +++ b/scripts/audit-production.test.mjs @@ -0,0 +1,115 @@ +import assert from "node:assert/strict"; +import { constants, createHash, generateKeyPairSync, privateEncrypt, sign } from "node:crypto"; +import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import test from "node:test"; +import { fileURLToPath } from "node:url"; +import braces from "braces"; +import forge from "node-forge"; +import { classifyAudit, securityPins, verifySecurityPins } from "./audit-production.mjs"; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const bracesFinding = { + source: 1240992, name: "braces", dependency: "braces", range: "<=3.0.3", + severity: "high", url: "https://github.com/advisories/GHSA-vfj7-8cjw-p6xm", +}; +const report = (finding = bracesFinding) => ({ + auditReportVersion: 2, + vulnerabilities: { + braces: { name: "braces", severity: "high", via: [finding] }, + consumer: { name: "consumer", severity: "high", via: ["braces", "consumer"] }, + }, +}); + +test("installed dependencies contain exactly the reviewed upstream fixes", () => verifySecurityPins()); + +test("audit recognizes only the fixed advisory, including transitive and cyclic paths", () => { + const result = classifyAudit(report()); + assert.equal(result.patched.length, 1); + assert.equal(result.unresolved.length, 0); +}); + +test("new or revised advisories still block", () => { + for (const change of [ + { url: "https://github.com/advisories/GHSA-new-advisory" }, + { source: 9999999 }, { range: "*" }, { severity: "critical" }, + { name: "another-package", dependency: "another-package" }, + ]) { + const result = classifyAudit(report({ ...bracesFinding, ...change })); + assert.equal(result.patched.length, 0); + assert.equal(result.unresolved.length, 1); + } + const mixed = report(); + mixed.vulnerabilities.braces.via.push({ ...bracesFinding, url: "https://github.com/advisories/GHSA-new-advisory" }); + assert.equal(classifyAudit(mixed).unresolved.length, 1); +}); + +test("malformed or incomplete audit reports fail closed", () => { + for (const invalid of [ + {}, { ...report(), error: { message: "registry unavailable" } }, + { ...report(), auditReportVersion: 3 }, + { auditReportVersion: 2, vulnerabilities: { consumer: { name: "consumer", severity: "high", via: ["missing"] } } }, + { auditReportVersion: 2, vulnerabilities: { consumer: { name: "consumer", severity: "high", via: ["consumer"] } } }, + ]) assert.throws(() => classifyAudit(invalid)); + assert.deepEqual(classifyAudit({ auditReportVersion: 2, vulnerabilities: {} }), { patched: [], unresolved: [] }); +}); + +test("audit rejects registry fallback, duplicate copies, and altered patch bytes", (t) => { + const directory = mkdtempSync(join(tmpdir(), "whip-dependency-pins-")); + t.after(() => rmSync(directory, { recursive: true, force: true })); + for (const file of ["package.json", "package-lock.json"]) cpSync(join(root, file), join(directory, file)); + for (const [name, pin] of Object.entries(securityPins)) { + for (const file of ["package.json", ...Object.keys(pin.files)]) { + const destination = join(directory, "node_modules", name, file); + mkdirSync(dirname(destination), { recursive: true }); + cpSync(join(root, "node_modules", name, file), destination); + } + } + verifySecurityPins(directory); + const lockFile = join(directory, "package-lock.json"); + const original = readFileSync(lockFile, "utf8"); + const lock = JSON.parse(original); + lock.packages["node_modules/braces"].resolved = "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"; + writeFileSync(lockFile, JSON.stringify(lock)); + assert.throws(() => verifySecurityPins(directory), /lock resolved changed/); + writeFileSync(lockFile, original); + const duplicate = JSON.parse(original); + duplicate.packages["node_modules/example/node_modules/braces"] = duplicate.packages["node_modules/braces"]; + writeFileSync(lockFile, JSON.stringify(duplicate)); + assert.throws(() => verifySecurityPins(directory), /Unexpected copies/); + writeFileSync(lockFile, original); + writeFileSync(join(directory, "node_modules/braces/lib/assert-depth.js"), "module.exports = () => {};\n"); + assert.throws(() => verifySecurityPins(directory), /does not contain the reviewed fix/); +}); + +test("braces rejects deep strings and ASTs before recursive stack exhaustion", () => { + const deep = "{".repeat(4000) + "a,b" + "}".repeat(4000); + assert.throws(() => braces(deep), SyntaxError); + let ast = { type: "text", value: "x" }; + for (let i = 0; i < 12000; i++) ast = { type: "brace", nodes: [ast] }; + for (const operation of [braces.compile, braces.expand, braces.stringify]) { + assert.throws(() => operation(ast), SyntaxError); + const cyclic = { type: "brace", nodes: [] }; + cyclic.nodes.push(cyclic); + assert.throws(() => operation(cyclic), /acyclic/); + } + assert.deepEqual(braces.expand("{a,b}{1..3}"), ["a1", "a2", "a3", "b1", "b2", "b3"]); + assert.doesNotThrow(() => braces("{".repeat(64) + "a,b" + "}".repeat(64))); +}); + +test("forge accepts valid signatures and rejects extra nested DigestAlgorithm elements", () => { + const keys = generateKeyPairSync("rsa", { modulusLength: 1024 }); + const publicKey = forge.pki.publicKeyFromPem(keys.publicKey.export({ type: "spki", format: "pem" })); + const message = Buffer.from("whip dependency security regression"); + const digest = createHash("sha256").update(message).digest(); + assert.equal(publicKey.verify(digest.toString("binary"), sign("sha256", message, keys.privateKey).toString("binary")), true); + + // SHA-256 DigestInfo with an extra OCTET STRING inside DigestAlgorithm. + // The unchanged registry release accepts this mathematically valid signature; + // the pinned fix must reject its malformed ASN.1 structure. + const digestInfo = Buffer.concat([Buffer.from("30343010060960864801650304020105000401000420", "hex"), digest]); + const encoded = Buffer.concat([Buffer.from([0, 1]), Buffer.alloc(128 - digestInfo.length - 3, 0xff), Buffer.from([0]), digestInfo]); + const malformed = privateEncrypt({ key: keys.privateKey, padding: constants.RSA_NO_PADDING }, encoded); + assert.throws(() => publicKey.verify(digest.toString("binary"), malformed.toString("binary")), /DigestInfo/); +}); From fd8df54986fbfc70a642965fe9b60166aba6575a Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 17:43:03 -0700 Subject: [PATCH 60/67] fix(deps): align docs router with patched Start release --- apps/docs/package.json | 2 +- docs/dependency-security.md | 4 ++- package-lock.json | 57 ++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 913125af9..3b0f53349 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -23,7 +23,7 @@ "dependencies": { "@base-ui/react": "1.8.0", "@stylexjs/stylex": "0.19.0", - "@tanstack/react-router": "1.170.32", + "@tanstack/react-router": "1.170.41", "@tanstack/react-start": "1.168.60", "react": "19.2.8", "react-dom": "19.2.8" diff --git a/docs/dependency-security.md b/docs/dependency-security.md index 0d15f8097..55758e4f6 100644 --- a/docs/dependency-security.md +++ b/docs/dependency-security.md @@ -8,7 +8,9 @@ remain unchanged. - Go 1.27.2 replaces 1.27.0. The refreshed `govulncheck` reports no reachable vulnerabilities; findings in unused dependency code remain visible. - TanStack Start 1.168.60 applies the same targeted version update proposed by - [#328](https://github.com/context-labs/whip/pull/328). + [#328](https://github.com/context-labs/whip/pull/328). The docs router is aligned + to Start's matching 1.170.41 version so prerendering resolves compatible SSR + exports; the desktop/web app's router pin remains unchanged. - The existing compatible ranges resolve patched `compression`, `shell-quote`, and `source-map-js` releases in the root lockfile. diff --git a/package-lock.json b/package-lock.json index f7d14f7ef..e54ea5bd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,7 @@ "dependencies": { "@base-ui/react": "1.8.0", "@stylexjs/stylex": "0.19.0", - "@tanstack/react-router": "1.170.32", + "@tanstack/react-router": "1.170.41", "@tanstack/react-start": "1.168.60", "react": "19.2.8", "react-dom": "19.2.8" @@ -103,6 +103,61 @@ "node": ">=24 <25" } }, + "apps/docs/node_modules/@tanstack/history": { + "version": "1.162.4", + "resolved": "https://registry.npmjs.org/@tanstack/history/-/history-1.162.4.tgz", + "integrity": "sha512-utTS5L2OkeYUzXGohL1Z8sefu1GLNOJcxe8Hd6iIdc/Xo1K1nDB2JEp4iSFhvYh33xKC9V91TxrS8qfrpoKobQ==", + "license": "MIT", + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "apps/docs/node_modules/@tanstack/react-router": { + "version": "1.170.41", + "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.170.41.tgz", + "integrity": "sha512-Mpvw8Wm5MGDbTqI8Yc9flLKxbOHwoWocv0H2aGKcgw2a017oK5nZWqa954P+DrUx/8fI98YNywnHP5XcD3tQ9w==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "@tanstack/react-store": "^0.11.2", + "@tanstack/router-core": "1.171.34", + "isbot": "^5.1.22" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "apps/docs/node_modules/@tanstack/router-core": { + "version": "1.171.34", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.171.34.tgz", + "integrity": "sha512-X+19pGuuLVPvvAvPYw9v/+ktRk5cCll8AtfpBpOhDRmVgUMrfqze0467xtq8YRVVs/mmo5rVtWn/7Tp32RDBKw==", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.162.4", + "cookie-es": "^3.0.0", + "seroval": "^1.6.7", + "seroval-plugins": "^1.6.7" + }, + "engines": { + "node": ">=20.19" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "apps/mobile": { "name": "@whip/mobile", "version": "0.1.0", From bea623177e36d47ad9f4472dc875025f426cafc1 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 17:50:11 -0700 Subject: [PATCH 61/67] fix(tooling): support patched Go compiler in analysis gates --- .github/workflows/ci.yml | 2 +- docs/dependency-security.md | 5 +++++ go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- internal/agent/decay_test.go | 4 ++-- internal/tui/links.go | 5 ++--- internal/tui/tui.go | 10 +++++----- 7 files changed, 36 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cef88c125..0f746d6ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,7 @@ jobs: # Pinned: "latest" is a moving target and older releases can't parse # Go 1.27 export data. Bump deliberately alongside the Go toolchain. # The enabled linters live in .golangci.yml (repo source of truth). - version: v2.13.1 + version: v2.14.0 - name: go mod tidy is a no-op run: | diff --git a/docs/dependency-security.md b/docs/dependency-security.md index 55758e4f6..92c13e7b1 100644 --- a/docs/dependency-security.md +++ b/docs/dependency-security.md @@ -7,6 +7,11 @@ remain unchanged. - Go 1.27.2 replaces 1.27.0. The refreshed `govulncheck` reports no reachable vulnerabilities; findings in unused dependency code remain visible. +- `golang.org/x/tools` 0.50.0 and `golangci-lint` 2.14.0 support the patched + compiler's export format. Older versions fail before running the analyzers. + The corresponding Go module minimums move with `x/tools`; analyzer rules and + coverage requirements remain unchanged. Four equivalent `CutLast` replacements + satisfy newly reported modernization findings in the agent tests and TUI. - TanStack Start 1.168.60 applies the same targeted version update proposed by [#328](https://github.com/context-labs/whip/pull/328). The docs router is aligned to Start's matching 1.170.41 version so prerendering resolves compatible SSR diff --git a/go.mod b/go.mod index d1024bd75..8c81d0afa 100644 --- a/go.mod +++ b/go.mod @@ -25,11 +25,11 @@ require ( github.com/tetratelabs/wazero v1.12.0 go.starlark.net v0.0.0-20260828210309-6dd8f160a37f golang.org/x/image v0.45.0 - golang.org/x/mod v0.39.0 - golang.org/x/net v0.58.0 - golang.org/x/sys v0.47.0 - golang.org/x/term v0.45.0 - golang.org/x/tools v0.49.0 + golang.org/x/mod v0.41.0 + golang.org/x/net v0.59.0 + golang.org/x/sys v0.48.0 + golang.org/x/term v0.46.0 + golang.org/x/tools v0.50.0 modernc.org/sqlite v1.57.0 ) @@ -71,8 +71,8 @@ require ( github.com/yuin/goldmark v1.7.17 // indirect github.com/yuin/goldmark-emoji v1.0.6 // indirect golang.org/x/oauth2 v0.35.0 // indirect - golang.org/x/sync v0.22.0 // indirect - golang.org/x/text v0.41.0 // indirect + golang.org/x/sync v0.23.0 // indirect + golang.org/x/text v0.42.0 // indirect golang.org/x/time v0.15.0 // indirect modernc.org/libc v1.74.4 // indirect modernc.org/mathutil v1.7.1 // indirect diff --git a/go.sum b/go.sum index 26b788743..96e8b8489 100644 --- a/go.sum +++ b/go.sum @@ -140,25 +140,25 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.45.0 h1:FMb1nTbH5H9vF55SriQHgFw5GnNL9Jg6L25BwXKzhB0= golang.org/x/image v0.45.0/go.mod h1:n62x/7RqlwXDvGsSU4u6IUTUf6KghUZ9Bt7cG/T9Fx4= -golang.org/x/mod v0.39.0 h1:UF5zwQdCRRUpHfyPwr7d4UrGiVeldIsogtzWVnczL74= -golang.org/x/mod v0.39.0/go.mod h1:bvIbwjQ0HUFFf5AKukeeYQG4ZBUG9yxQbR9aEweIwYY= -golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= -golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c= +golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o= +golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= +golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= -golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= -golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= -golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= -golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= -golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= +golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= -golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= +golang.org/x/tools v0.50.0 h1:c2ifzfcuY7L90lZ2aKd8S4K2NpASF08SZx9ZuJkHmSU= +golang.org/x/tools v0.50.0/go.mod h1:7ulVMw3831Mwi5EZD6RomGyffr4VFjuNYXf2BbCEAV0= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= modernc.org/cc/v4 v4.29.1 h1:MKgdCV3WykTSPqpVrnxdEDS0HEd2FHpKZDzxzU5LyeI= diff --git a/internal/agent/decay_test.go b/internal/agent/decay_test.go index 1793a1123..348e0c4ca 100644 --- a/internal/agent/decay_test.go +++ b/internal/agent/decay_test.go @@ -181,8 +181,8 @@ func TestDecayKeepsSpillPath(t *testing.T) { t.Fatalf("decayed placeholder should keep the spill path, got %q", got) } // the referenced file exists and holds the full output - i := strings.LastIndex(got, "full output: ") - path := strings.TrimSuffix(strings.TrimSpace(got[i+len("full output: "):]), "⟩") + _, outputPath, _ := strings.CutLast(got, "full output: ") + path := strings.TrimSuffix(strings.TrimSpace(outputPath), "⟩") data, err := os.ReadFile(path) if err != nil || len(data) != 60_000 { t.Errorf("spill file should hold the full 60k output (len=%d, err=%v)", len(data), err) diff --git a/internal/tui/links.go b/internal/tui/links.go index a821987f7..87d15458e 100644 --- a/internal/tui/links.go +++ b/internal/tui/links.go @@ -81,12 +81,11 @@ func linkifyFilePathsWith(s string, exists func(string) bool, uri func(string, s // checked here: paths with a slash take any extension, bare filenames need // at least two letters (links_test.go yes, tui.go no — too prose-shaped). func isFileRef(path string) bool { - dot := strings.LastIndexByte(path, '.') - if dot < 0 { + _, ext, found := strings.CutLast(path, ".") + if !found { // no extension: only a slashed path counts (internal/tui, /etc/hostname) return strings.Contains(path, "/") } - ext := path[dot+1:] if strings.ContainsRune(ext, '/') { return false // dot was in a directory segment } diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 951e05afe..8b1e64fe0 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -816,11 +816,11 @@ func procHasAncestor(pid int, want string) bool { // ppid is field 4 of /proc/PID/stat; the (comm) field before it may // contain spaces/parens, so split after the LAST ')'. Fields after it // are: state ppid ... — ppid is fields[1] of the remainder. - idx := bytes.LastIndexByte(stat, ')') - if idx < 0 { + _, remainder, found := bytes.CutLast(stat, []byte(")")) + if !found { return false } - fields := strings.Fields(string(stat[idx+1:])) + fields := strings.Fields(string(remainder)) if len(fields) < 2 { return false } @@ -968,9 +968,9 @@ func detectColorScheme() string { // Pure so the no-query-reply behavior is unit-testable: inside tmux the ONLY // acceptable outcomes are COLORFGBG or neutral, never a dark assumption. func fallbackScheme(inTmux bool, colorfgbg string) (light, ok bool, how string) { - if i := strings.LastIndex(colorfgbg, ";"); i >= 0 { + if _, background, found := strings.CutLast(colorfgbg, ";"); found { var bg int - if _, err := fmt.Sscanf(colorfgbg[i+1:], "%d", &bg); err == nil { + if _, err := fmt.Sscanf(background, "%d", &bg); err == nil { // standard palette: 0-6 dark, 7+ light (15 = white) return bg == 7 || bg >= 8, true, "COLORFGBG (query failed)" } From 64e37008d48b55ee520d0acbc087738fccf6bcab Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 18:13:05 -0700 Subject: [PATCH 62/67] test: preserve provider, cancellation and trace behavior under patched Go --- docs/dependency-security.md | 9 + .../client/root_client_cancellation_test.go | 139 ++++++++++++ internal/llm/messages_test.go | 197 ++++++++++++++++++ internal/llm/presentation_test.go | 47 +++++ internal/llm/responses_test.go | 158 ++++++++++++++ 5 files changed, 550 insertions(+) create mode 100644 internal/client/root_client_cancellation_test.go diff --git a/docs/dependency-security.md b/docs/dependency-security.md index 92c13e7b1..ce9c0c3a2 100644 --- a/docs/dependency-security.md +++ b/docs/dependency-security.md @@ -55,6 +55,15 @@ valid RSA signatures, malformed nested RSA DigestInfo, unknown advisories, registry fallback and patch tampering. The SDK job runs this gate before the existing frontend and SDK acceptance checks. +The compiler update also changes statement weights in coverage profiles. On +identical source, Go 1.27.0 records 38,455 statements and Go 1.27.2 records 37,134; +702 blocks receive different weights. The hosted tests all passed, but coverage +moved from 90.2% to 89.8%. The 90% floor is retained. Additional regressions cover +provider image/request encoding, malformed responses and continuation limits, +truncation and thinking preservation, cancellation of waiting client calls, and +bounded presentation copy isolation and UTF-8 handling. These tests change no +runtime behavior. + ## Returning to registry releases When upstream publishes fixes, review the release against these patches, remove diff --git a/internal/client/root_client_cancellation_test.go b/internal/client/root_client_cancellation_test.go new file mode 100644 index 000000000..80137513d --- /dev/null +++ b/internal/client/root_client_cancellation_test.go @@ -0,0 +1,139 @@ +package client + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/context-labs/whip/internal/protocol" +) + +func TestRootClientWaitingRequestsUnblockOnCancellation(t *testing.T) { + t.Parallel() + for _, name := range []string{"caller", "client"} { + t.Run(name, func(t *testing.T) { + t.Parallel() + connecting := make(chan struct{}) + client, err := NewRootClient(RootClientOptions{ + ClientID: "waiting", RootID: "root", + Connector: func(ctx context.Context, _ map[string]int64) (RootConnection, error) { + close(connecting) + <-ctx.Done() + return nil, ctx.Err() + }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = client.Close() }) + client.Start() + <-connecting + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + action := RootAction{CommandID: "command", RootID: "root", Operation: "submit"} + permission := RootAction{CommandID: "permission", RootID: "root", Operation: "permission.decide"} + requests := []func() error{ + func() error { return client.WaitLive(ctx) }, + func() error { _, err := client.Command(ctx, action); return err }, + func() error { + _, err := client.ValidateProvider(ctx, protocol.ProviderValidateParams{}) + return err + }, + func() error { + _, err := client.DecidePermission( + ctx, + permission, + "permission-id", + true, + "approved", + "", + ) + return err + }, + } + results := make(chan error, len(requests)) + for _, request := range requests { + go func() { results <- request() }() + } + if name == "caller" { + cancel() + } else if err := client.Close(); err != nil { + t.Fatal(err) + } + deadline := time.NewTimer(5 * time.Second) + defer deadline.Stop() + for range requests { + select { + case err := <-results: + if !errors.Is(err, context.Canceled) { + t.Fatalf("waiting request lost cancellation: %v", err) + } + case <-deadline.C: + t.Fatal("request remained blocked after cancellation") + } + } + }) + } +} + +type providerValidationConnection struct { + *staticRootConnection + validate func() error +} + +func (c *providerValidationConnection) ValidateProvider( + context.Context, + protocol.ProviderValidateParams, +) (protocol.ProviderValidateResult, error) { + return protocol.ProviderValidateResult{}, c.validate() +} + +func TestRootClientProviderValidationPreservesFailureAndCancellation(t *testing.T) { + t.Parallel() + for _, cancelled := range []bool{false, true} { + name := "provider failure" + if cancelled { + name = "caller cancellation" + } + t.Run(name, func(t *testing.T) { + t.Parallel() + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + failure := errors.New("provider validation unavailable") + calls := 0 + connection := &providerValidationConnection{ + staticRootConnection: newStaticRootConnection(), + validate: func() error { + calls++ + if cancelled { + cancel() + } + return failure + }, + } + client, err := NewRootClient(RootClientOptions{ + ClientID: "validate", RootID: "root", + Connector: func(context.Context, map[string]int64) (RootConnection, error) { return connection, nil }, + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = client.Close() }) + client.Start() + ready, stop := context.WithTimeout(ctx, 5*time.Second) + defer stop() + if err := client.WaitLive(ready); err != nil { + t.Fatal(err) + } + _, err = client.ValidateProvider(ctx, protocol.ProviderValidateParams{}) + want := failure + if cancelled { + want = context.Canceled + } + if !errors.Is(err, want) || calls != 1 { + t.Fatalf("validation failure was retried or replaced: calls=%d err=%v", calls, err) + } + }) + } +} diff --git a/internal/llm/messages_test.go b/internal/llm/messages_test.go index b7d4a420b..5eeea88fa 100644 --- a/internal/llm/messages_test.go +++ b/internal/llm/messages_test.go @@ -2,13 +2,210 @@ package llm import ( "encoding/json" + "errors" "io" "maps" "net/http" + "reflect" "strings" "testing" ) +func TestMessagesImageWireContract(t *testing.T) { + t.Parallel() + for _, tc := range []struct{ name, url, mediaType, data string }{ + {name: "jpeg", url: "data:image/jpeg;base64,aW1hZ2U=", mediaType: "image/jpeg", data: "aW1hZ2U="}, + {name: "missing media type", url: "data:;base64,aW1hZ2U=", mediaType: "image/png", data: "aW1hZ2U="}, + {name: "missing separator", url: "data:image/jpeg,aW1hZ2U=", mediaType: "image/png", data: "aW1hZ2U="}, + {name: "malformed URL", url: "invalid", mediaType: "image/png"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + part := ImagePart("jpg", []byte("image")) + part.ImageURL.URL = tc.url + part.W, part.H = 100, 200 + temperature, topP := 0.25, 0.9 + body, err := encodeMessages(Request{ + Model: "model", Temperature: &temperature, TopP: &topP, + Messages: []Message{ + {Role: "user", Content: "Describe", Parts: []ContentPart{{Type: "text", Text: "details"}, part}}, + {Role: "assistant", Content: "An image."}, + }, + }) + if err != nil { + t.Fatal(err) + } + var wire struct { + Messages []struct { + Role string `json:"role"` + Content []map[string]any `json:"content"` + } `json:"messages"` + Temperature float64 `json:"temperature"` + TopP float64 `json:"top_p"` + } + if err := json.Unmarshal(body, &wire); err != nil { + t.Fatal(err) + } + want := []map[string]any{ + {"type": "text", "text": "Describe"}, + {"type": "text", "text": "details"}, + {"type": "image", "source": map[string]any{ + "type": "base64", "media_type": tc.mediaType, "data": tc.data, + }}, + } + if len(wire.Messages) != 2 || !reflect.DeepEqual(wire.Messages[0].Content, want) { + t.Fatalf("multimodal payload changed: %s", body) + } + if wire.Messages[1].Content[0]["text"] != "An image." || + wire.Temperature != temperature || wire.TopP != topP { + t.Fatalf("assistant text or sampling settings changed: %s", body) + } + }) + } +} + +func TestMessagesRejectMalformedInput(t *testing.T) { + t.Parallel() + call := ToolCall{ID: "call", Type: "function"} + call.Function.Name, call.Function.Arguments = "read", "{broken" + for _, tc := range []struct { + name string + request Request + want string + }{ + {name: "role", request: Request{Messages: []Message{{Role: "unknown"}}}, want: "unsupported message role"}, + {name: "empty user", request: Request{Messages: []Message{{Role: "user"}}}, want: "no content"}, + { + name: "missing image", want: "no URL", + request: Request{Messages: []Message{{Role: "user", Parts: []ContentPart{{Type: "image_url"}}}}}, + }, + { + name: "unknown part", want: "unsupported content part", + request: Request{Messages: []Message{{Role: "user", Parts: []ContentPart{{Type: "audio"}}}}}, + }, + { + name: "invalid arguments", want: "arguments", + request: Request{Messages: []Message{{Role: "assistant", ToolCalls: []ToolCall{call}}}}, + }, + {name: "invalid schema", request: Request{Tools: []Tool{NewTool("read", "Read", "{broken")}}, want: "schema"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + body, err := encodeMessages(tc.request) + if err == nil || !strings.Contains(err.Error(), tc.want) || len(body) != 0 { + t.Fatalf("invalid input produced a request: body=%q err=%v", body, err) + } + }) + } +} + +func TestMessagesTransportFailuresPreserveErrors(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + name, url string + status int + transportError error + }{ + {name: "invalid endpoint", url: "://invalid"}, + {name: "transport failure", url: "https://example.test", transportError: io.ErrUnexpectedEOF}, + {name: "provider rejection", url: "https://example.test", status: http.StatusBadRequest}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + client := NewMessagesClient(tc.url, "") + client.HTTP = &http.Client{Transport: rtFunc(func(*http.Request) (*http.Response, error) { + if tc.transportError != nil { + return nil, tc.transportError + } + return &http.Response{ + StatusCode: tc.status, Header: http.Header{}, + Body: io.NopCloser(strings.NewReader(`{"error":{"message":"invalid request"}}`)), + }, nil + })} + message, _, err := client.messagesOnce( + t.Context(), + []byte(`{}`), + nil, + nil, + nil, + ) + if err == nil || message.Content != "" || len(message.ToolCalls) != 0 { + t.Fatalf("failed request published output: %+v %v", message, err) + } + if tc.transportError != nil && !errors.Is(err, tc.transportError) { + t.Fatalf("transport error identity lost: %v", err) + } + }) + } +} + +func TestMessagesTruncationDiscardsToolsAndRetainsThinking(t *testing.T) { + t.Parallel() + stream := ": keepalive\ndata: invalid JSON\n" + sse( + event("content_block_delta", map[string]any{ + "index": 1, "delta": map[string]any{"type": "input_json_delta", "partial_json": "ignored"}, + }), + event("content_block_delta", map[string]any{ + "index": 2, "delta": map[string]any{"type": "thinking_delta", "thinking": "Plan"}, + }), + event("content_block_delta", map[string]any{ + "index": 3, "delta": map[string]any{"type": "signature_delta", "signature": "opaque"}, + }), + event("content_block_start", map[string]any{ + "index": 0, "content_block": map[string]any{"type": "tool_use", "id": "call", "name": "read"}, + }), + event("content_block_delta", map[string]any{ + "index": 0, "delta": map[string]any{"type": "input_json_delta", "partial_json": "{}"}, + }), + event("message_delta", map[string]any{"delta": map[string]any{"stop_reason": "max_tokens"}}), + ) + var thinking string + message, _, err := parseMessagesSSE( + strings.NewReader(stream), + nil, + func(delta string) { thinking += delta }, + nil, + ) + if err != nil || len(message.ToolCalls) != 0 || thinking != "Plan" { + t.Fatalf("truncated tools or thinking changed: %+v %v", message, err) + } + if message.Content != "\n[response truncated by max_tokens; tool calls discarded]" || + !reflect.DeepEqual(message.Thinking, []ThinkingBlock{{Thinking: "Plan"}, {Signature: "opaque"}}) { + t.Fatalf("truncation receipt or thinking order changed: %+v", message) + } +} + +func TestMessagesStreamFailuresNeverLookComplete(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + name string + reader io.Reader + want string + }{ + {name: "missing completion", reader: strings.NewReader(sse(event("message_start", nil))), want: "completion marker"}, + { + name: "provider error", want: "rejected", + reader: strings.NewReader(sse(event("error", map[string]any{ + "error": map[string]any{"message": "rejected"}, + }))), + }, + {name: "read failure", reader: accountingBrokenReader{}, want: io.ErrUnexpectedEOF.Error()}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + message, _, err := parseMessagesSSE( + tc.reader, + nil, + nil, + nil, + ) + if err == nil || !strings.Contains(err.Error(), tc.want) || len(message.ToolCalls) != 0 { + t.Fatalf("incomplete stream accepted: %+v %v", message, err) + } + }) + } +} + type rtFunc func(*http.Request) (*http.Response, error) func (f rtFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } diff --git a/internal/llm/presentation_test.go b/internal/llm/presentation_test.go index 7870ddf0f..457a1f050 100644 --- a/internal/llm/presentation_test.go +++ b/internal/llm/presentation_test.go @@ -2,10 +2,57 @@ package llm import ( "encoding/json" + "strconv" "strings" "testing" + "unicode/utf8" ) +func TestBoundPresentationRetainsRecentHostsWithoutMutatingHistory(t *testing.T) { + t.Parallel() + index := 2 + value := &TranscriptPresentation{ + Version: 1, + DesignContext: &DesignContextPresentation{ScreenshotPartIndex: &index}, + Parts: []PresentationPart{{ID: "part", Kind: "tool", Hosts: []PresentationHost{}}}, + } + for i := range 129 { + value.Parts[0].Hosts = append(value.Parts[0].Hosts, PresentationHost{InvocationID: strconv.Itoa(i), Name: "read"}) + } + bounded := BoundPresentation(value, 128<<10) + part := &bounded.Parts[0] + if len(part.Hosts) != 128 || part.Hosts[0].InvocationID != "1" || part.Omitted != 1 { + t.Fatalf("recent hosts or omission receipt changed: %+v", part) + } + part.Hosts[0].Name = "changed" + *bounded.DesignContext.ScreenshotPartIndex = 9 + if value.Parts[0].Hosts[1].Name != "read" || len(value.Parts[0].Hosts) != 129 || index != 2 { + t.Fatal("bounded presentation changed previously retained history") + } +} + +func TestBoundPresentationTrimsReasoningAndOversizedIdentities(t *testing.T) { + t.Parallel() + text := strings.Repeat("思", 30000) + value := &TranscriptPresentation{Version: 1, Parts: []PresentationPart{{ID: "reason", Text: text}}} + bounded := BoundPresentation(value, 64<<10) + encoded, err := json.Marshal(bounded) + if err != nil || len(encoded) > 64<<10 || len(bounded.Parts) != 1 { + t.Fatalf("reasoning exceeds presentation budget: bytes=%d err=%v", len(encoded), err) + } + if bounded.Parts[0].Omitted == 0 || !utf8.ValidString(bounded.Parts[0].Text) || value.Parts[0].Text != text { + t.Fatal("reasoning trim lost omission metadata, split UTF-8, or mutated history") + } + oversized := &TranscriptPresentation{Version: 1, Parts: []PresentationPart{{ID: strings.Repeat("x", 1024)}}} + trimmed := BoundPresentation(oversized, 256) + if len(trimmed.Parts) != 0 || trimmed.Omitted != 1 || len(oversized.Parts) != 1 { + t.Fatal("oversized identity was not omitted independently") + } + if got := PresentationExcerpt("short", 128); got != "short" { + t.Fatalf("short excerpt changed: %q", got) + } +} + func TestPresentationDoesNotEnterProviderOrAccounting(t *testing.T) { message := Message{Role: "assistant", Content: "hello", Presentation: &TranscriptPresentation{Version: 1, Parts: []PresentationPart{{ID: "p", Kind: "reasoning", Text: "private display"}}}} plain := message diff --git a/internal/llm/responses_test.go b/internal/llm/responses_test.go index 92a6d2f86..ce65e8f99 100644 --- a/internal/llm/responses_test.go +++ b/internal/llm/responses_test.go @@ -19,6 +19,164 @@ func decodeFixture(stream string) (Message, Usage, error) { return decodeResponses(strings.NewReader(stream), "account", "model", func(string) {}, func(string) {}, func(string, string, string) {}) } +func TestResponsesRejectMalformedHistory(t *testing.T) { + t.Parallel() + image := ImagePart("png", []byte("image")) + for _, tc := range []struct { + name string + message Message + tools []Tool + want string + }{ + {name: "unknown role", message: Message{Role: "unknown"}, want: "message role"}, + { + name: "missing image", want: "invalid image", + message: Message{Role: "user", Parts: []ContentPart{{Type: "image_url"}}}, + }, + {name: "assistant image", message: Message{Role: "assistant", Parts: []ContentPart{image}}, want: "invalid image"}, + { + name: "unknown part", want: "unsupported OpenAI message content", + message: Message{Role: "user", Parts: []ContentPart{{Type: "audio"}}}, + }, + { + name: "unsupported tool", want: "function tools", + message: Message{Role: "user", Content: "hi"}, tools: []Tool{{Type: "computer"}}, + }, + {name: "malformed continuation", message: Message{ + Role: "assistant", Continuation: ResponseContinuation{AccountID: "account", Model: "model", Items: "{broken"}, + }, want: "continuation is malformed"}, + {name: "invalid continuation item", message: Message{ + Role: "assistant", Continuation: ResponseContinuation{AccountID: "account", Model: "model", Items: `["invalid"]`}, + }, want: "malformed output item"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + body, err := encodeResponses(Request{Model: "model", Messages: []Message{tc.message}, Tools: tc.tools}, "account") + if err == nil || !strings.Contains(err.Error(), tc.want) || len(body) != 0 { + t.Fatalf("invalid history produced a provider request: %q %v", body, err) + } + }) + } + message := Message{Role: "assistant", Continuation: ResponseContinuation{ + AccountID: "account", Model: "model", Items: strings.Repeat(" ", maxResponseBytes+1), + }} + _, err := encodeResponses(Request{Model: "model", Messages: []Message{message}}, "account") + if err == nil || !strings.Contains(err.Error(), "size limit") { + t.Fatalf("oversized continuation accepted: %v", err) + } +} + +func TestResponsesOutputValidationPreservesRefusalAndBounds(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + name string + items []json.RawMessage + want string + }{ + {name: "item count", items: make([]json.RawMessage, maxResponseItems+1), want: "too many output items"}, + {name: "malformed item", items: []json.RawMessage{json.RawMessage(`"invalid"`)}, want: "malformed output item"}, + { + name: "unexpected role", want: "unexpected output role", + items: []json.RawMessage{json.RawMessage(`{"type":"message","role":"user"}`)}, + }, + { + name: "unexpected content", want: "unsupported output content", + items: []json.RawMessage{json.RawMessage( + `{"type":"message","role":"assistant","content":[{"type":"audio"}]}`, + )}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + message, err := responseMessage(tc.items) + if err == nil || !strings.Contains(err.Error(), tc.want) || len(message.ToolCalls) != 0 { + t.Fatalf("invalid output accepted: %+v %v", message, err) + } + }) + } + _, err := responseMessage([]json.RawMessage{json.RawMessage(strings.Repeat(" ", maxResponseBytes+1))}) + if err == nil || !strings.Contains(err.Error(), "size limit") { + t.Fatalf("oversized provider output accepted: %v", err) + } + message, err := responseMessage([]json.RawMessage{ + json.RawMessage(`{"type":"message","role":"assistant","content":[{"type":"refusal","refusal":"Cannot comply."}]}`), + }) + if err != nil || message.Content != "Cannot comply." || len(message.ToolCalls) != 0 { + t.Fatalf("refusal was not preserved as text: %+v %v", message, err) + } +} + +func TestResponsesMalformedFramesNeverPublishContinuation(t *testing.T) { + t.Parallel() + for _, tc := range []struct{ name, frame, want string }{ + { + name: "malformed item", want: "malformed output item", + frame: `{"type":"response.output_item.added","item":"bad"}`, + }, + { + name: "orphan arguments", want: "without a call", + frame: `{"type":"response.function_call_arguments.delta","output_index":0,"delta":"{}"}`, + }, + { + name: "malformed terminal", want: "malformed terminal response", + frame: `{"type":"response.completed","response":"bad"}`, + }, + { + name: "malformed usage", want: "malformed token usage", + frame: `{"type":"response.completed","response":{"status":"completed","usage":"bad"}}`, + }, + { + name: "invalid usage", want: "usage", + frame: `{"type":"response.completed","response":{"status":"completed",` + + `"usage":{"input_tokens":-1,"output_tokens":2}}}`, + }, + {name: "invalid completed item", frame: responseFixture(`["bad"]`), want: "malformed output item"}, + } { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + // No trailing blank line: the last frame must still be validated at EOF. + message, _, err := decodeFixture("data: " + tc.frame) + if err == nil || !strings.Contains(err.Error(), tc.want) || message.Continuation.Items != "" { + t.Fatalf("malformed frame published continuation: %+v %v", message, err) + } + }) + } + message, _, err := decodeResponses( + accountingBrokenReader{}, + "account", + "model", + func(string) {}, + func(string) {}, + func(string, string, string) {}, + ) + if !errors.Is(err, io.ErrUnexpectedEOF) || message.Continuation.Items != "" { + t.Fatalf("stream read failure lost: %+v %v", message, err) + } +} + +func TestResponsesRetainTextPartsAndRejectSamplingOptions(t *testing.T) { + t.Parallel() + request := Request{Messages: []Message{{Role: "user", Parts: []ContentPart{{Type: "text", Text: "part text"}}}}} + body, err := encodeResponses(request, "account") + if err != nil || !strings.Contains(string(body), `"text":"part text"`) { + t.Fatalf("text part lost: %s %v", body, err) + } + value := 0.5 + for _, tc := range []struct { + name string + temperature, topP *float64 + }{{name: "temperature", temperature: &value}, {name: "top_p", topP: &value}} { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + input := request + input.Temperature, input.TopP = tc.temperature, tc.topP + if _, err := encodeResponses(input, "account"); err == nil || !strings.Contains(err.Error(), "unsupported") { + t.Fatalf("unsupported sampling option accepted: %v", err) + } + }) + } +} + func TestResponsesToolContinuationRoundTrip(t *testing.T) { items := `[{"type":"reasoning","id":"r1","encrypted_content":"opaque-state","summary":[]},` + `{"type":"message","id":"m1","role":"assistant","phase":"commentary","content":[{"type":"output_text","text":"Checking."}]},` + From bee34d819d9ecceb64b8421a2c631ba90c7eb4a7 Mon Sep 17 00:00:00 2001 From: Amar Singh <asingh263199@gmail.com> Date: Fri, 25 Sep 2026 16:07:56 +0000 Subject: [PATCH 63/67] Preserve Go build settings in managed child processes (cherry picked from commit 8884403a7e23572c95c1d760c44eafa140d89e4c) --- docs/concurrency.md | 7 +++ internal/capability/process.go | 4 ++ internal/capability/process_go_test.go | 65 ++++++++++++++++++++++++++ internal/capability/process_test.go | 37 ++++++++++++++- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 internal/capability/process_go_test.go diff --git a/docs/concurrency.md b/docs/concurrency.md index e28da4267..04147d271 100644 --- a/docs/concurrency.md +++ b/docs/concurrency.md @@ -248,6 +248,13 @@ Shell and kernel subprocesses run in managed process groups. This is operational containment, not a security sandbox against another hostile process already running as the same OS user. +Managed host processes inherit the Go build settings `GOCACHE`, `GOMODCACHE`, +`GOPATH`, `GOROOT`, `GOTOOLCHAIN`, and `GOFLAGS` captured when the process manager +starts. This preserves preloaded modules and toolchains in offline environments. +Explicit child-process settings take precedence over that snapshot. Other Go +variables, including credential-bearing proxy/auth settings, are not implicitly +inherited; the allowlist is in `internal/capability/process.go`. + ## Gateway process ownership The socket-only daemon owns execution; `internal/webgateway` owns HTTP/WS diff --git a/internal/capability/process.go b/internal/capability/process.go index 7820d8062..7736964af 100644 --- a/internal/capability/process.go +++ b/internal/capability/process.go @@ -372,6 +372,10 @@ func allowedBaseEnvironment(name string) bool { "TMPDIR", "TMP", "TEMP", "LANG", "LANGUAGE", "TERM", "COLORTERM", "NO_COLOR": return true + case "GOCACHE", "GOMODCACHE", "GOPATH", "GOROOT", "GOTOOLCHAIN", "GOFLAGS": + // Keep the host's Go toolchain and preloaded caches usable offline. + // Do not allow GO* wholesale: proxy/auth settings can carry credentials. + return true } return name == buildinfo.Env("HOME") || strings.HasPrefix(name, "LC_") } diff --git a/internal/capability/process_go_test.go b/internal/capability/process_go_test.go new file mode 100644 index 000000000..564906310 --- /dev/null +++ b/internal/capability/process_go_test.go @@ -0,0 +1,65 @@ +//go:build darwin || linux + +package capability + +import ( + "bytes" + "context" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" +) + +func TestProcessGoUsesPreloadedModuleCacheOffline(t *testing.T) { + goBin, err := exec.LookPath("go") + if err != nil { + t.Skip("Go executable is not on PATH") + } + work := t.TempDir() + cache := t.TempDir() + const dependency = "example.com/whip-cache-test" + // Listing the module graph needs cached metadata, so this fixture exercises + // a real Go command without downloads or toolchain compilation. + mod := filepath.Join(cache, "cache", "download", dependency, "@v", "v1.0.0.mod") + if err := os.MkdirAll(filepath.Dir(mod), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(mod, []byte("module "+dependency+"\n\ngo 1.20\n"), 0o644); err != nil { + t.Fatal(err) + } + info := filepath.Join(filepath.Dir(mod), "v1.0.0.info") + if err := os.WriteFile(info, []byte(`{"Version":"v1.0.0","Time":"2020-01-01T00:00:00Z"}`), 0o644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(work, "go.mod"), []byte("module example.com/app\n\ngo 1.20\n\nrequire "+dependency+" v1.0.0\n"), 0o644); err != nil { + t.Fatal(err) + } + t.Setenv("GOMODCACHE", cache) + t.Setenv("GOCACHE", t.TempDir()) + t.Setenv("GOPATH", t.TempDir()) + t.Setenv("GOTOOLCHAIN", "local") + t.Setenv("GOFLAGS", "-mod=mod") + m := NewProcessManager() + t.Cleanup(func() { _ = m.Close() }) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + var stdout, stderr bytes.Buffer + p, err := m.Start(ctx, "root", goBin, []string{"list", "-m", "all"}, ProcessOptions{ + Cwd: work, + // Explicitly prohibit downloads and ignore host-specific Go settings. + Env: map[string]string{"GOPROXY": "off", "GOSUMDB": "off", "GOENV": "off", "GOWORK": "off"}, + Stdin: strings.NewReader(""), Stdout: &stdout, Stderr: &stderr, + }) + if err != nil { + t.Fatal(err) + } + if err := p.Wait(); err != nil { + t.Fatalf("offline module lookup failed: %v\n%s", err, stderr.String()) + } + if !strings.Contains(stdout.String(), dependency+" v1.0.0\n") { + t.Fatalf("cached dependency missing from module graph: %s", stdout.String()) + } +} diff --git a/internal/capability/process_test.go b/internal/capability/process_test.go index 7ff08c9a1..1bfede6aa 100644 --- a/internal/capability/process_test.go +++ b/internal/capability/process_test.go @@ -61,8 +61,23 @@ func TestProcessEnvironmentCwdAndDescriptors(t *testing.T) { t.Setenv("SSH_AUTH_SOCK", "/daemon-agent") t.Setenv("RANDOM_DAEMON_SECRET", "daemon-random") t.Setenv("WHIPCODE_HOME", "/snapshot-whip-home") + goEnvironment := map[string]string{ + "GOCACHE": "/snapshot-go-build-cache", + "GOMODCACHE": "/snapshot-go-module-cache", + "GOPATH": "/snapshot-gopath", + "GOROOT": "/snapshot-goroot", + "GOTOOLCHAIN": "local", + "GOFLAGS": "-mod=mod", + } + for name, value := range goEnvironment { + t.Setenv(name, value) + } + t.Setenv("GOPROXY", "https://user:secret@proxy.invalid") + t.Setenv("GOAUTH", "daemon-auth-command") + t.Setenv("GO_PRIVATE_TOKEN", "daemon-go-secret") m := NewProcessManager() t.Setenv("HOME", "/changed-after-snapshot") + t.Setenv("GOMODCACHE", "/changed-after-snapshot") f, err := os.CreateTemp(t.TempDir(), "descriptor") if err != nil { @@ -112,7 +127,12 @@ func TestProcessEnvironmentCwdAndDescriptors(t *testing.T) { t.Errorf("%s = %q, want %q", name, env[name], want) } } - for _, name := range []string{"PROVIDER_API_KEY", "SSH_AUTH_SOCK", "RANDOM_DAEMON_SECRET"} { + for name, want := range goEnvironment { + if env[name] != want { + t.Errorf("%s = %q, want %q", name, env[name], want) + } + } + for _, name := range []string{"PROVIDER_API_KEY", "SSH_AUTH_SOCK", "RANDOM_DAEMON_SECRET", "GOPROXY", "GOAUTH", "GO_PRIVATE_TOKEN"} { if _, ok := env[name]; ok { t.Errorf("daemon environment leaked %s", name) } @@ -130,6 +150,21 @@ func TestProcessEnvironmentCwdAndDescriptors(t *testing.T) { if built, err := m.environment(nil); err != nil || !slices.IsSorted(built) { t.Errorf("environment not deterministically sorted: %v, %v", built, err) } + // Launchers that own exec.Cmd receive the captured build settings too; + // explicit per-process values still take precedence. + child, err := m.ChildEnvironment(map[string]string{"GOFLAGS": "-mod=readonly"}) + if err != nil { + t.Fatal(err) + } + childEnv := envMap(child) + for name, want := range goEnvironment { + if name == "GOFLAGS" { + want = "-mod=readonly" + } + if childEnv[name] != want { + t.Errorf("ChildEnvironment %s = %q, want %q", name, childEnv[name], want) + } + } if err := m.Close(); err != nil { t.Fatal(err) } From cf701307194932f32895510de2b3fc97d556959d Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 19:44:40 -0700 Subject: [PATCH 64/67] fix(ci): validate docs prerequisites and reviewed release transition --- .github/workflows/docs-deploy.yml | 8 ++ apps/docs/README.md | 5 + docs/release-readiness.md | 48 +++++++++ scripts/backend-compat/README.md | 9 ++ scripts/backend-compat/release-transition.mjs | 100 ++++++++++++++++++ .../release-transition.test.mjs | 81 ++++++++++++++ scripts/backend-compat/run.mjs | 8 +- 7 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 docs/release-readiness.md create mode 100644 scripts/backend-compat/release-transition.mjs create mode 100644 scripts/backend-compat/release-transition.test.mjs diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 2f94e747a..ca1728267 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -25,6 +25,10 @@ jobs: with: ref: ${{ github.sha }} persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 + with: + go-version-file: go.mod + cache: true - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7 with: node-version: '24' @@ -32,6 +36,10 @@ jobs: - run: npm ci env: ELECTRON_SKIP_BINARY_DOWNLOAD: '1' + - name: Initialize protocol artifacts and SDK for example tests + run: | + npm run generate + npm run build - run: npm install --prefix "$RUNNER_TEMP/wrangler" --no-save wrangler@4.140.0 - run: echo "$RUNNER_TEMP/wrangler/node_modules/.bin" >> "$GITHUB_PATH" - run: npm run check:docs diff --git a/apps/docs/README.md b/apps/docs/README.md index 7671613fd..7e546b566 100644 --- a/apps/docs/README.md +++ b/apps/docs/README.md @@ -20,6 +20,11 @@ npm run storybook:docs # http://localhost:6007 npm run build:storybook:docs ``` +On a clean checkout, run `npm run generate` with the Go version in `go.mod` +before `test:docs`. The published SDK examples are typechecked against the actual +SDK source and its generated protocol declarations. This test prerequisite does +not add an SDK or daemon dependency to the deployed site. + Install Chromium once with `npx playwright install chromium` (CI uses `--with-deps`). Browser tests require a completed `build:docs`, build Storybook automatically, and start static servers on ports 3101 and 6008. Content-independent diff --git a/docs/release-readiness.md b/docs/release-readiness.md new file mode 100644 index 000000000..571976169 --- /dev/null +++ b/docs/release-readiness.md @@ -0,0 +1,48 @@ +# Development release after backend reorganization + +The reorganization froze development at `271c0f8d2a35648d1b45056d57432590b783483c` +(protocol 6.9). The release PR targets older main +`88764670f1c6e2a57e22463e96cfb0d6021aea33` (protocol 6.8). Strict equality with +that older main also rejects intentional features already present before the +reorganization. The frozen baseline, SDK, generated protocol, database schema, +and runtime behavior are unchanged by this release-readiness repair. + +## Historical differences checked for this release + +| Origin | Observable change in the deterministic compatibility fixture | +| --- | --- | +| [f62b5eec6](https://github.com/context-labs/whip/commit/f62b5eec628b2d583793aa788dc2eb677941e0f8) — concrete effort vocabulary | Protocol minor 8 → 9; new root session and agent effort resolves from empty to `low`. | +| [54fca9c1a](https://github.com/context-labs/whip/commit/54fca9c1af25fb85bbf581f05ed5a401bcc5fb2f) — title generation | Removes `session.autotitle`; advertises `session_title_notifications`; admission emits one `session.title.updated` event before `turn.started`. This advances subsequent event/trace sequences and cursors by one. The fallback title grows from 64 to 128 characters, and user messages retain their originating turn. | +| [12f0ea076](https://github.com/context-labs/whip/commit/12f0ea076) — native folder creation | Adds `host.directory.create` beside `host.directory.pick`. | +| [b8cc56a48](https://github.com/context-labs/whip/commit/b8cc56a48d781998784fc7ce1cc541bea2cd59fb) — conversation cleanup | An empty compaction model selects the conversation's model/provider rather than a built-in DeepSeek route. Configuration/provider revision hashes change accordingly. Assistant messages retain recording timestamps. | + +These differences were reproduced in both Linux and macOS release CI artifacts; +their normalized parent and frozen-reference transcripts match across platforms. +They are expectations for this exact historical release pair, not permission +for further changes to these fields. + +`scripts/backend-compat/release-transition.mjs` checks the old values before +constructing the expected release transcript. It requires that transcript to +match both the independently built frozen reference and the candidate, including +all untouched fields, event order, payloads, counts, identities and cursors. +The ordinary immediate-base comparison remains strict for every other base SHA. +Existing fixed-SDK, generated-artifact, lifecycle, schema, checkpoint, trace and +base → candidate → base rollback checks remain enabled. + +## Docs deployment prerequisite + +The deployment workflow omitted protocol generation after generated files +stopped being tracked. The same prerequisite was already restored in regular +docs CI by [567bdebba](https://github.com/context-labs/whip/commit/567bdebbae9aa21a7a09a7686a979824ea998a51). +Set up Go from `go.mod`, generate the protocol and build the SDK before checking +the published examples. The static site still has no SDK or daemon runtime +dependency. + +## Release acceptance + +Require full CI, the docs preview deployment, and isolated desktop acceptance +before merging development to main. Exercise REPL/child state and traces through +the compatibility lifecycle/rollback scenarios; verify the shared renderer's +REPL, agent, provider and effort controls; and run the staged desktop lifecycle +smoke against temporary homes. These checks use local fixture providers and +must not consume personal provider credentials or existing sessions. diff --git a/scripts/backend-compat/README.md b/scripts/backend-compat/README.md index b9bb74128..b15d88fe8 100644 --- a/scripts/backend-compat/README.md +++ b/scripts/backend-compat/README.md @@ -62,6 +62,15 @@ forces two separate fixture fragments; smaller fragments could validly coalesce and would be a poor exact-event regression oracle. Comparator tests prove that response, omission, error, cursor, event order/count and identity mutations fail. +The release from main `88764670` to the pre-reorganization development baseline +has an explicit, commit-scoped expectation for previously reviewed protocol 6.8 +→ 6.9 features. See [release readiness](../../docs/release-readiness.md) for the +source commits and every expected difference. The gate checks those exact old +values and requires the result to match both the frozen reference and candidate. +It does not skip the immediate-base comparison or normalize away changed fields. +All other base revisions retain strict equality, and all rollback checks remain +enabled. The frozen baseline and source/artifact freeze are unchanged. + This is a cross-cutting regression gate, not exhaustive behavioral equivalence. It does not replace existing provider encoding/retry tests, detailed trace body and pagination tests, REPL/mail/budget tests, or product acceptance. Add focused diff --git a/scripts/backend-compat/release-transition.mjs b/scripts/backend-compat/release-transition.mjs new file mode 100644 index 000000000..e4ba54d72 --- /dev/null +++ b/scripts/backend-compat/release-transition.mjs @@ -0,0 +1,100 @@ +import assert from 'node:assert/strict'; +import { compare } from './compare.mjs'; + +// The already reviewed features between main and the frozen pre-reorganization +// development baseline. This expectation applies to this exact pair only. +// Provenance and scope: docs/release-readiness.md. +export const releaseTransition = { + base: '88764670f1c6e2a57e22463e96cfb0d6021aea33', + baseline: '271c0f8d2a35648d1b45056d57432590b783483c', +}; + +function replace(object, key, before, after) { + assert.ok(Object.hasOwn(object, key), `missing release source field ${key}`); + assert.deepEqual(object[key], before, `unexpected release source field ${key}`); + object[key] = after; +} + +function add(object, key, value) { + assert.ok(!Object.hasOwn(object, key), `release source already has ${key}`); + object[key] = value; +} + +export function expectedReleaseTranscript(parent) { + const expected = structuredClone(parent); + const { initialization, configuration, updated, provider, initial, snapshot, history, live, replay } = expected; + + // f62b5eec6: protocol 6.9 and concrete effort resolved at session creation. + replace(initialization, 'protocol_minor', 8, 9); + for (const state of [initial, snapshot]) { + replace(state.meta, 'effort', '', 'low'); + replace(state.agents[0], 'effort', '', 'low'); + } + + // b8cc56a48: compaction defaults to the conversation model/provider. Revision + // hashes are exact fixture values, not wildcarded configuration differences. + for (const state of [configuration, updated]) replace(state, 'compact_model', 'deepseek-v4-flash-0731', ''); + replace(configuration, 'revision', 'f82bc34858a0838f80a01e6e9b9c319905987aa2721f374d499a3b918f555f85', '4f2ca9fffdfa2e329309d36d357715e0abdaca3765524f3d651a0dbaef8de834'); + for (const state of [updated, provider]) replace(state, 'revision', 'a5719c0971e0b596bcc0ae551e8d8f85b84c0f28a3337b8252b416a3b271e44f', 'aa5d3e546d8cbfd6980e2452c78200a2419b5d88ea4d1b35fd61ad745d2a3b68'); + + // 12f0ea076: create a folder from the native directory picker. + const operations = initialization.operations; + assert.ok(!operations.some(operation => operation.name === 'host.directory.create')); + const picker = operations.findIndex(operation => operation.name === 'host.directory.pick'); + assert.ok(picker >= 0, 'release source lost directory picker'); + operations.splice(picker, 0, { name: 'host.directory.create', surface: 'rpc', execution: 'ephemeral', permission: 'host-runtime' }); + + // 54fca9c1a: title ownership moved to admission, replacing the explicit + // autotitle command with a notification and an ordered durable title event. + const autotitle = operations.findIndex(operation => operation.name === 'session.autotitle'); + assert.ok(autotitle >= 0, 'release source lost autotitle'); + assert.deepEqual(operations[autotitle], { name: 'session.autotitle', surface: 'runtime', execution: 'command', permission: 'root-association' }); + operations.splice(autotitle, 1); + for (const capabilities of [initialization.capabilities, initialization.negotiated_capabilities]) { + assert.ok(!capabilities.includes('session_title_notifications')); + } + initialization.capabilities.push('session_title_notifications'); + const engine = initialization.negotiated_capabilities.indexOf('execution_engines'); + assert.ok(engine >= 0, 'release source lost execution engine capability'); + initialization.negotiated_capabilities.splice(engine, 0, 'session_title_notifications'); + const title = 'A'.repeat(127) + '…'; + replace(snapshot.meta, 'title', 'A'.repeat(63) + '…', title); + for (const events of [live, replay.events]) { + assert.deepEqual(events.map(event => event.kind), ['command.queued', 'turn.started', 'span.started', 'stream.text', 'stream.text', 'turn.succeeded', 'span.ended']); + for (let i = 0; i < events.length; i++) { + assert.equal(events[i].seq, String(i + 1)); + if (i === 0) continue; + if (events[i].kind.startsWith('span.')) replace(events[i].payload, 'updated_seq', String(i + 1), String(i + 2)); + events[i].seq = String(i + 2); + } + const event = { root_id: events[0].root_id, seq: '2', kind: 'session.title.updated', payload: { title } }; + if (Object.hasOwn(events[0], 'subscription_id')) event.subscription_id = events[0].subscription_id; + events.splice(1, 0, event); + } + replace(replay, 'latest', '7', '8'); + replace(snapshot, 'cursor', '7', '8'); + replace(snapshot.accounting, 'revision', '7', '8'); + replace(snapshot.agents[0].last_turn, 'event_seq', '6', '7'); + for (const messages of [snapshot.messages, history.messages.map(entry => entry.message)]) { + assert.equal(messages[0].role, 'user'); + add(messages[0], 'presentation', { version: 1, turn_id: snapshot.agents[0].last_turn.turn_id }); + // b8cc56a48: preserve assistant recording time in the durable transcript. + assert.equal(messages[1].role, 'assistant'); + add(messages[1], 'sent_at', '<timestamp>'); + } + return expected; +} + +export function comparePRBase(parent, candidate, { baseRevision, baselineRevision, baseline, label }) { + if (baseRevision !== releaseTransition.base) { + compare(parent, candidate, label); + return 'strict'; + } + assert.equal(baselineRevision, releaseTransition.baseline, 'release expectation belongs to a different frozen baseline'); + const expected = expectedReleaseTranscript(parent); + // Prove the exception describes the pre-reorganization reference itself. + // A new candidate response can never become its own compatibility oracle. + compare(expected, baseline, `${label}: reviewed pre-reorganization transition`); + compare(expected, candidate, label); + return 'reviewed 6.8 to 6.9 transition'; +} diff --git a/scripts/backend-compat/release-transition.test.mjs b/scripts/backend-compat/release-transition.test.mjs new file mode 100644 index 000000000..f37b210dd --- /dev/null +++ b/scripts/backend-compat/release-transition.test.mjs @@ -0,0 +1,81 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { comparePRBase, releaseTransition } from './release-transition.mjs'; + +function transcript(upgraded) { + const revision = upgraded ? 'aa5d3e546d8cbfd6980e2452c78200a2419b5d88ea4d1b35fd61ad745d2a3b68' : 'a5719c0971e0b596bcc0ae551e8d8f85b84c0f28a3337b8252b416a3b271e44f'; + const title = 'A'.repeat(upgraded ? 127 : 63) + '…'; + const kinds = ['command.queued', ...(upgraded ? ['session.title.updated'] : []), 'turn.started', 'span.started', 'stream.text', 'stream.text', 'turn.succeeded', 'span.ended']; + const events = kinds.map((kind, i) => ({ root_id: 'root', seq: String(i + 1), kind, + payload: kind === 'session.title.updated' ? { title } : kind.startsWith('span.') ? { updated_seq: String(i + 1), trace_id: 'trace' } : { text: 'preserved payload' }, + })); + const messages = () => [ + { role: 'user', content: 'input', ...(upgraded ? { presentation: { version: 1, turn_id: 'turn' } } : {}) }, + { role: 'assistant', content: 'output', ...(upgraded ? { sent_at: '<timestamp>' } : {}) }, + ]; + const effort = upgraded ? 'low' : ''; + return { + initialization: { + protocol_minor: upgraded ? 9 : 8, + capabilities: ['commands', 'execution_engines', ...(upgraded ? ['session_title_notifications'] : [])], + negotiated_capabilities: ['commands', ...(upgraded ? ['session_title_notifications'] : []), 'execution_engines'], + operations: [ + ...(upgraded ? [{ name: 'host.directory.create', surface: 'rpc', execution: 'ephemeral', permission: 'host-runtime' }] : []), + { name: 'host.directory.pick', surface: 'rpc', execution: 'query', permission: 'host-runtime' }, + ...(!upgraded ? [{ name: 'session.autotitle', surface: 'runtime', execution: 'command', permission: 'root-association' }] : []), + ], + }, + configuration: { compact_model: upgraded ? '' : 'deepseek-v4-flash-0731', revision: upgraded ? '4f2ca9fffdfa2e329309d36d357715e0abdaca3765524f3d651a0dbaef8de834' : 'f82bc34858a0838f80a01e6e9b9c319905987aa2721f374d499a3b918f555f85' }, + updated: { compact_model: upgraded ? '' : 'deepseek-v4-flash-0731', revision }, + provider: { revision, name: 'unchanged provider' }, + initial: { meta: { effort }, agents: [{ effort }] }, + snapshot: { meta: { effort, title }, agents: [{ effort, last_turn: { turn_id: 'turn', event_seq: upgraded ? '7' : '6' } }], + cursor: upgraded ? '8' : '7', accounting: { revision: upgraded ? '8' : '7' }, messages: messages() }, + history: { messages: messages().map(message => ({ message })) }, + live: events.map(event => ({ ...structuredClone(event), subscription_id: 'subscription' })), + replay: { latest: upgraded ? '8' : '7', events }, + error: { code: -32000, message: 'unchanged error', data: null }, + }; +} + +const options = () => ({ baseRevision: releaseTransition.base, baselineRevision: releaseTransition.baseline, baseline: transcript(true), label: 'test release' }); + +test('accepts the exact reviewed historical transition without modifying inputs', () => { + const parent = transcript(false), candidate = transcript(true); + assert.equal(comparePRBase(parent, candidate, options()), 'reviewed 6.8 to 6.9 transition'); + assert.deepEqual(parent, transcript(false)); + assert.deepEqual(candidate, transcript(true)); +}); + +for (const [name, mutate] of Object.entries({ + effort: value => { value.snapshot.meta.effort = 'high'; }, + configuration: value => { value.configuration.revision = 'unexpected'; }, + provider: value => { value.provider.name = 'changed provider'; }, + error: value => { value.error.data = {}; }, + title: value => { value.live[1].payload.title = 'different title'; }, + eventOrder: value => { value.live.reverse(); }, + eventCount: value => { value.replay.events.splice(1, 1); }, + cursor: value => { value.snapshot.cursor = '9'; }, + identity: value => { value.history.messages[0].message.presentation.turn_id = 'other-turn'; }, + addedField: value => { value.snapshot.meta.new_field = true; }, +})) test(`rejects an additional candidate ${name} change`, () => { + const candidate = transcript(true); mutate(candidate); + assert.throws(() => comparePRBase(transcript(false), candidate, options()), assert.AssertionError); +}); + +test('an unexpected historical value cannot be overwritten by a release expectation', () => { + const parent = transcript(false); parent.initial.meta.effort = 'off'; + assert.throws(() => comparePRBase(parent, transcript(true), options()), /unexpected release source field effort/); +}); + +test('release expectations must describe the independently built frozen baseline', () => { + const config = options(); config.baseline.updated.compact_model = 'another-model'; + assert.throws(() => comparePRBase(transcript(false), transcript(true), config), /reviewed pre-reorganization transition/); + assert.throws(() => comparePRBase(transcript(false), transcript(true), { ...options(), baselineRevision: '0'.repeat(40) }), /different frozen baseline/); +}); + +test('every other PR base retains exact transcript equality', () => { + const config = { ...options(), baseRevision: '1'.repeat(40) }; + assert.throws(() => comparePRBase(transcript(false), transcript(true), config), assert.AssertionError); + assert.equal(comparePRBase(transcript(true), transcript(true), config), 'strict'); +}); diff --git a/scripts/backend-compat/run.mjs b/scripts/backend-compat/run.mjs index 63a7b2715..054691409 100644 --- a/scripts/backend-compat/run.mjs +++ b/scripts/backend-compat/run.mjs @@ -7,6 +7,7 @@ import { join, resolve } from 'node:path'; import { parseArgs } from 'node:util'; import { fileURLToPath } from 'node:url'; import { compare } from './compare.mjs'; +import { comparePRBase } from './release-transition.mjs'; import { loadSDK, smoke, lifecycle, rollback } from './scenarios.mjs'; const { values } = parseArgs({ options: { candidate: { type: 'string' }, base: { type: 'string' }, output: { type: 'string' } } }); @@ -83,7 +84,7 @@ try { for (const path of manifest.generatedPaths) compare(await tree(join(baseline, path)), await tree(join(candidate, path)), `fresh generated ${path}`); compare(await tree(join(baseline, 'packages/sdk/dist')), await tree(join(candidate, 'packages/sdk/dist')), 'compiled SDK artifact freeze'); evidence.artifacts = { baselineBinary: digest(await readFile(baseBinary)), parentBinary: digest(await readFile(parentBinary)), candidateBinary: digest(await readFile(candidateBinary)), sdk: await tree(join(baseline, 'packages/sdk/dist')), protocol: await tree(join(baseline, 'packages/protocol/generated')), lockfile: digest(await readFile(join(baseline, 'package-lock.json'))) }; - await command(process.execPath, ['--test', fileURLToPath(new URL('./compare.test.mjs', import.meta.url))]); + await command(process.execPath, ['--test', ...['compare.test.mjs', 'release-transition.test.mjs'].map(name => fileURLToPath(new URL(name, import.meta.url)))]); const sdk = await loadSDK(baseline); // Every invocation gets new state, including repeated calibration runs. const runs = await mkdtemp(join(output, 'runs-')); @@ -103,7 +104,10 @@ try { compare(reference, actual, `${transport} fixed-SDK differential`); const parentTranscript = parentBinary === baseBinary ? reference : await smoke(sdk, parentBinary, join(runs, `parent-${transport}`), transport); await writeFile(join(runs, `parent-${transport}.json`), JSON.stringify(parentTranscript, null, 2)); - compare(parentTranscript, actual, `${transport} immediate-PR-base differential`); + evidence.results[`${transport}PRBase`] = comparePRBase(parentTranscript, actual, { + baseRevision: evidence.parentRevision, baselineRevision: manifest.revision, + baseline: reference, label: `${transport} immediate-PR-base differential`, + }); evidence.results[transport] = 'passed: calibrated response/error/event transcript'; } for (const [name, binary] of [['baseline', baseBinary], ['candidate', candidateBinary]]) { From d68879672e7c2c42f3e2b4384cbc2ee4ac464211 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 20:00:24 -0700 Subject: [PATCH 65/67] fix(web): let latest navigation supersede pending anchor restoration --- .github/workflows/ci.yml | 8 ++++++++ apps/web/scripts/chat-activity.mjs | 7 ++++++- apps/web/scripts/history-gap.mjs | 17 +++++++++-------- apps/web/scripts/repl-viewer.mjs | 25 +++++++++++++++++-------- apps/web/scripts/settings.mjs | 14 +++++++++----- docs/frontend.md | 4 +++- docs/release-readiness.md | 16 ++++++++++++++++ packages/app/src/reading-list.tsx | 3 +++ 8 files changed, 71 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76c17679f..bcc3215e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -225,6 +225,11 @@ jobs: - run: node packages/ui/tests/csp.mjs - run: npm run test:packed -w @whip/ui - run: WHIP_WEB_BROWSERS=chromium,firefox node apps/web/scripts/browser.mjs + - name: REPL, provider settings, and child-agent acceptance + run: | + node apps/web/scripts/repl-viewer.mjs + node apps/web/scripts/settings.mjs + WHIP_CHAT_AGENTS_ONLY=1 node apps/web/scripts/chat-activity.mjs - run: node apps/web/scripts/model-picker.mjs - run: node apps/web/scripts/snapshot-refresh.mjs - run: node --test apps/web/scripts/performance-probes.test.mjs @@ -247,6 +252,9 @@ jobs: path: | /tmp/whip-web-browser-results /tmp/whip-web-snapshot-refresh + /tmp/whip-repl-viewer-results + /tmp/whip-settings-browser-results + /tmp/whip-chat-activity-results packages/ui/ui-test-results docs: diff --git a/apps/web/scripts/chat-activity.mjs b/apps/web/scripts/chat-activity.mjs index 7d71512ce..b970e5fda 100644 --- a/apps/web/scripts/chat-activity.mjs +++ b/apps/web/scripts/chat-activity.mjs @@ -230,7 +230,12 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await page.goBack(); await expect(dock.getByRole('status')).toHaveText('Waiting for agents'); await expect(group).toHaveCount(1); - await dock.getByRole('button', { name: 'Pause activity animation' }).click(); + // Motion is now owned by Appearance settings, not the activity status button. + await page.locator('#whip-settings-link').click(); + await page.getByRole('navigation', { name: 'Settings categories', exact: true }).getByRole('button', { name: 'Appearance', exact: true }).click(); + await page.getByRole('combobox', { name: 'Reduce motion', exact: true }).click(); + await page.getByRole('option', { name: 'Reduce', exact: true }).click(); + await page.getByRole('button', { name: 'Back to workspace', exact: true }).click(); await expect(page.locator('html')).toHaveAttribute('data-motion', 'reduce'); await expect(dock.locator('[data-activity-animation]')).toHaveAttribute('data-activity-animation', 'static'); await expect(working.locator('[data-activity-animation]')).toHaveAttribute('data-activity-animation', 'static'); diff --git a/apps/web/scripts/history-gap.mjs b/apps/web/scripts/history-gap.mjs index 0d2466a74..84a8352e3 100644 --- a/apps/web/scripts/history-gap.mjs +++ b/apps/web/scripts/history-gap.mjs @@ -33,17 +33,18 @@ export async function checkHistoryRecovery({ page, client, fixture, root, direct const session = client.session(root); const view = createSessionView(session); await view.start(); - const findGap = async () => { - await reading.hover(); await page.mouse.wheel(0, -1); + const findGap = async (region = reading) => { + await region.hover(); await page.mouse.wheel(0, -1); await page.waitForTimeout(200); - await reading.evaluate(element => { element.dispatchEvent(new Event('scrollend')); element.scrollTop = 0; }); - for (let attempt = 0; attempt < 100; attempt++) { - const gap = reading.locator('[data-history-gap]').first(); - const visible = await reading.evaluate(element => { + await region.evaluate(element => { element.dispatchEvent(new Event('scrollend')); element.scrollTop = 0; }); + // A bounded 512-record window can exceed 100 viewports of code/output. + for (let attempt = 0; attempt < 512; attempt++) { + const gap = region.locator('[data-history-gap]').first(); + const visible = await region.evaluate(element => { const gap = element.querySelector('[data-history-gap]'); if (!gap) { element.scrollTop += element.clientHeight * 0.6; return false; } const top = gap.getBoundingClientRect().top - element.getBoundingClientRect().top; - if (top >= 0 && top < element.clientHeight - 100) return true; + if (top >= 0 && top + gap.getBoundingClientRect().height <= element.clientHeight) return true; element.scrollTop += top - 100; return false; }); if (visible) return gap; @@ -106,7 +107,7 @@ export async function checkHistoryRecovery({ page, client, fixture, root, direct const readsBeforeSwitch = requests.length; await page.getByRole('button', { name: 'REPL', exact: true }).click(); const notebook = page.getByRole('region', { name: 'REPL executions', exact: true }); - await expect(notebook.locator('[data-history-gap]')).toContainText("Couldn't load messages"); + await expect(await findGap(notebook)).toContainText("Couldn't load messages"); await page.goBack(); await findGap(); assert.equal(requests.length, readsBeforeSwitch, 'Chat and REPL share the failed range without refetching'); const retry = control.getByRole('button', { name: 'Retry', exact: true }); diff --git a/apps/web/scripts/repl-viewer.mjs b/apps/web/scripts/repl-viewer.mjs index e1801d019..12e6358cc 100644 --- a/apps/web/scripts/repl-viewer.mjs +++ b/apps/web/scripts/repl-viewer.mjs @@ -58,6 +58,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' const ready = async (id, mode) => { await (mode === 'repl' ? notebook(id) : mode === 'trace' ? panel(id).locator('[data-session-view="trace"]') : panel(id).getByLabel('Message WHIP', { exact: true })).waitFor(); await expect(page.locator('html')).toHaveAttribute('data-theme', /claude-code|light|dark/); + await expect(page.locator('[data-startup-phase="visible"]')).toBeVisible(); }; const action = async (id, label) => { await page.locator(`[data-workspace-tab="${id}"]`).getByRole('tab').click({ button: 'right' }); @@ -81,21 +82,24 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' const backwardReads = agentId => frames.filter(frame => frame.method === 'history.page' && frame.params.agent_id === agentId && frame.params.before_seq > 0); const scrollPage = async (region, agentId) => { const count = backwardReads(agentId).length; - await region.dispatchEvent('wheel'); + const threshold = await region.evaluate(element => element.getAttribute('aria-label') === 'Conversation' ? Math.min(2400, Math.max(800, 2 * element.clientHeight)) : 256); + const start = threshold + 100; + await region.dispatchEvent('wheel', { deltaY: -1 }); await eventually(async () => { - // Newly prepended rows are measured lazily when this position is visited. - await region.evaluate(element => { element.scrollTop = 350; }); + // Stay near the actual threshold so the next visible anchor is mounted. + await region.evaluate((element, offset) => { element.scrollTop = offset; }, start); await region.evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)))); - return Math.abs((await region.evaluate(element => element.scrollTop)) - 350) < 1 && await anchor(region); + return Math.abs((await region.evaluate(element => element.scrollTop)) - start) < 1 && await anchor(region); }, { description: 'settled position above pagination threshold' }); // Scroll the real viewport through the threshold. Capture the visible row in // the same task, before the scroll handler can start its asynchronous read. - const before = await region.evaluate(element => { - element.scrollTop = 200; + const before = await region.evaluate((element, offset) => { + element.dispatchEvent(new WheelEvent('wheel', { bubbles: true, deltaY: -1 })); + element.scrollTop = offset; const top = element.getBoundingClientRect().top; const row = [...element.querySelectorAll('[data-reading-id]')].find(item => item.getBoundingClientRect().bottom > top); return row ? { id: row.dataset.readingId, offset: row.getBoundingClientRect().top - top } : null; - }); + }, threshold - 50); assert.ok(before, 'No visible row before pagination'); await eventually(() => { const reads = backwardReads(agentId); @@ -124,8 +128,12 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' }; // The last cell's ordinal is the loaded count; the REPL has no summary toolbar. const loadedCells = async id => { - await latest(id); const last = notebook(id).locator('[data-repl-cell]').last(); + await last.waitFor({ state: 'attached' }); + // Loading a sparse page can remove Latest while a click is waiting for it. + // Count the loaded rows by scrolling the viewport after cells arrive. + await notebook(id).evaluate(element => { element.scrollTop = element.scrollHeight; }); + await notebook(id).evaluate(() => new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)))); await expect(last).toBeVisible(); return Number((await last.getAttribute('aria-label')).match(/^Execution (\d+)$/)[1]); }; @@ -350,6 +358,7 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await latest(moved); const live = notebook(moved).locator('[data-repl-cell]').filter({ hasText: 'live' }).last(); await expect(live).toContainText('Writing'); + await expect(live).toBeInViewport(); await expect(live).toContainText('print("live'); await step('progress'); await expect(live).toContainText('Running'); diff --git a/apps/web/scripts/settings.mjs b/apps/web/scripts/settings.mjs index 14892cc92..8832f4702 100644 --- a/apps/web/scripts/settings.mjs +++ b/apps/web/scripts/settings.mjs @@ -5,9 +5,6 @@ import { join } from 'node:path'; import { chromium, firefox, expect } from '@playwright/test'; import { startFixture } from '../../../packages/sdk/scripts/fixture.mjs'; -process.env.OPENROUTER_API_KEY = 'fixture-settings-key'; -process.env.INFERENCE_API_KEY = ''; - const results = process.env.WHIP_SETTINGS_RESULTS ?? '/tmp/whip-settings-browser-results'; await mkdir(results, { recursive: true }); const axeSource = await readFile(createRequire(import.meta.url).resolve('axe-core/axe.min.js'), 'utf8'); @@ -38,8 +35,15 @@ for (const engine of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split await page.getByRole('option', { name: option, exact: true }).click(); }; try { - await writeFile(join(fixture.directory, 'home', 'config.json'), JSON.stringify({ defaultModel: 'settings-model', defaultProvider: 'openrouter', models: { 'settings-model': { providers: ['openrouter'] }, 'unsaved-settings-model': { providers: ['openrouter'] } } })); - await writeFile(join(fixture.directory, 'home', 'models.json'), JSON.stringify({ openrouter: { baseUrl: 'https://openrouter.ai/api/v1', fetchedAt: new Date().toISOString(), models: [{ id: 'settings-model' }, { id: 'unsaved-settings-model', reasoning_efforts: ['low', 'high'] }] } })); + // TestMain intentionally clears inherited provider keys. Configure a local + // fixture route explicitly so this acceptance test never needs an account. + const providerBaseURL = fixture.info.frontend + '/v1'; + await writeFile(join(fixture.directory, 'home', 'config.json'), JSON.stringify({ + defaultModel: 'settings-model', defaultProvider: 'openrouter', + providers: { openrouter: { baseUrl: providerBaseURL, api: 'openai-completions', auth: 'none' } }, + models: { 'settings-model': { providers: ['openrouter'] }, 'unsaved-settings-model': { providers: ['openrouter'] } }, + })); + await writeFile(join(fixture.directory, 'home', 'models.json'), JSON.stringify({ openrouter: { baseUrl: providerBaseURL, fetchedAt: new Date().toISOString(), models: [{ id: 'settings-model' }, { id: 'unsaved-settings-model', reasoningEfforts: ['low', 'high'] }] } })); await page.goto(chatURL); const composer = page.locator('[data-whip-composer]'); await composer.waitFor(); diff --git a/docs/frontend.md b/docs/frontend.md index ec9b05cfa..7a0968cb2 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -2106,7 +2106,9 @@ reading anchors; it does not undo filesystem effects. TanStack Virtual bounds rendered rows. Follow its measurement/anchor integration when changing variable-height Markdown, code, or tool output. Preserve the reader's position while paging or streaming; show Jump to latest when away from -live output. A replaced/evicted anchor should degrade visibly to retained history, +live output. An explicit Jump to latest supersedes older reading-position restores, +including an insertion-anchor restore started while its history fetch is pending. +A replaced/evicted anchor should degrade visibly to retained history, not fetch unlimited history to recover an exact pixel. Code rendering is lazy, bounded, copyable text; do not inject untrusted HTML or treat model output as UI instructions. Keep URL/content checks in the existing rendering paths. diff --git a/docs/release-readiness.md b/docs/release-readiness.md index 571976169..017a6be29 100644 --- a/docs/release-readiness.md +++ b/docs/release-readiness.md @@ -46,3 +46,19 @@ the compatibility lifecycle/rollback scenarios; verify the shared renderer's REPL, agent, provider and effort controls; and run the staged desktop lifecycle smoke against temporary homes. These checks use local fixture providers and must not consume personal provider credentials or existing sessions. + +## Follow-up renderer acceptance repair + +The release smoke exposed an existing `ReadingList` race: after Latest fetched +newer history, an insertion-anchor restore created during that fetch could pull +the REPL back to older rows. The separate renderer fix cancels that restore after +the read completes, while preserving the existing user-input cancellation guard. +No SDK, protocol, provider, or persistence semantics change. + +The focused REPL, settings, and child-agent renderer checks run in the SDK CI +job on Chromium and Firefox, with their artifacts retained alongside browser +acceptance evidence. Their setup waits for startup to finish, exercises an upward +scroll from outside both history-prefetch thresholds, and uses an explicit local +provider route instead of inherited account keys. The activity test changes +reduced motion through the current Appearance controls. These test-harness +repairs retain the existing behavioral assertions. diff --git a/packages/app/src/reading-list.tsx b/packages/app/src/reading-list.tsx index 0a3d1c8b7..27ff21658 100644 --- a/packages/app/src/reading-list.tsx +++ b/packages/app/src/reading-list.tsx @@ -492,6 +492,9 @@ export function ReadingList<Row extends { id: string; seq?: number }>({ finally { setLoadingLatest(false); } if (request !== latestIntent.current || !viewport.current) return; } + // The history read can start a new insertion-anchor restore while awaited. + // The explicit Latest action supersedes that older reading position. + stopRestore(); intent.current = undefined; const root = viewport.current; jumping.current = animate && chatFollow && motion && !!root && root.scrollHeight - root.scrollTop - root.clientHeight > 2; From ddca8e62e9b149683217e123705be0da2c097c5d Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 20:04:00 -0700 Subject: [PATCH 66/67] test(web): isolate activity and history recovery acceptance fixtures --- .github/workflows/ci.yml | 6 ++++-- apps/web/scripts/chat-activity.mjs | 3 ++- docs/release-readiness.md | 9 +++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcc3215e7..b00d272ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -225,11 +225,13 @@ jobs: - run: node packages/ui/tests/csp.mjs - run: npm run test:packed -w @whip/ui - run: WHIP_WEB_BROWSERS=chromium,firefox node apps/web/scripts/browser.mjs - - name: REPL, provider settings, and child-agent acceptance + - name: Renderer release acceptance run: | node apps/web/scripts/repl-viewer.mjs node apps/web/scripts/settings.mjs - WHIP_CHAT_AGENTS_ONLY=1 node apps/web/scripts/chat-activity.mjs + WHIP_CHAT_AGENTS_ONLY=1 WHIP_CHAT_ACTIVITY_RESULTS=/tmp/whip-chat-activity-results/agents node apps/web/scripts/chat-activity.mjs + WHIP_CHAT_ACTIVITY_RESULTS=/tmp/whip-chat-activity-results/activity node apps/web/scripts/chat-activity.mjs + WHIP_CHAT_HISTORY_ONLY=1 WHIP_CHAT_ACTIVITY_RESULTS=/tmp/whip-chat-activity-results/history node apps/web/scripts/chat-activity.mjs - run: node apps/web/scripts/model-picker.mjs - run: node apps/web/scripts/snapshot-refresh.mjs - run: node --test apps/web/scripts/performance-probes.test.mjs diff --git a/apps/web/scripts/chat-activity.mjs b/apps/web/scripts/chat-activity.mjs index b970e5fda..c3eb09e88 100644 --- a/apps/web/scripts/chat-activity.mjs +++ b/apps/web/scripts/chat-activity.mjs @@ -458,7 +458,8 @@ for (const name of (process.env.WHIP_WEB_BROWSERS ?? 'chromium,firefox').split(' await expect(notebook).toContainText('Review complete.'); await page.goBack(); await expect(reading).toBeVisible(); - await checkHistoryRecovery({ page, client, fixture, root, directory, name }); + // History recovery runs through WHIP_CHAT_HISTORY_ONLY in its own fixture. + // This scenario's retained activity can evict the interior gap it exercises. // Normal scrolling must leave the activity dock available without extra subscriptions. await reading.evaluate(element => { element.scrollTop = 300; }); await expect(page.getByRole('textbox', { name: 'Message WHIP', exact: true })).toBeInViewport(); diff --git a/docs/release-readiness.md b/docs/release-readiness.md index 017a6be29..b44488431 100644 --- a/docs/release-readiness.md +++ b/docs/release-readiness.md @@ -55,10 +55,15 @@ the REPL back to older rows. The separate renderer fix cancels that restore afte the read completes, while preserving the existing user-input cancellation guard. No SDK, protocol, provider, or persistence semantics change. -The focused REPL, settings, and child-agent renderer checks run in the SDK CI -job on Chromium and Firefox, with their artifacts retained alongside browser +The REPL, settings, child-agent, activity, and history-recovery checks run in SDK CI +on Chromium and Firefox, with their artifacts retained alongside browser acceptance evidence. Their setup waits for startup to finish, exercises an upward scroll from outside both history-prefetch thresholds, and uses an explicit local provider route instead of inherited account keys. The activity test changes reduced motion through the current Appearance controls. These test-harness repairs retain the existing behavioral assertions. + +Activity and history recovery each use their existing standalone mode with a +fresh fixture. Reusing the activity stress fixture can evict the interior range +the recovery scenario expects to retain; the independent runs keep all of the +existing recovery, request-bound, identity, and reading-anchor assertions. From 7c8b15c68f54d3b3e778c140423fd87171c8e597 Mon Sep 17 00:00:00 2001 From: Sam Heutmaker <samheutmaker@gmail.com> Date: Fri, 16 Oct 2026 20:05:06 -0700 Subject: [PATCH 67/67] ci: validate UI repair after retargeting to development